Logo Search packages:      
Sourcecode: ddccontrol version File versions  Download package

main.c

/*
    ddc/ci command line tool
    Copyright(c) 2004 Oleg I. Vdovikin (oleg@cs.msu.su)
    Copyright(c) 2004-2006 Nicolas Boichat (nicolas@boichat.ch)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "config.h"
#include "ddcci.h"
#include "monitor_db.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define RETRYS 3 /* number of retrys */

static void dumpctrl(struct monitor* mon, unsigned char ctrl, int force)
{
      unsigned short value, maximum;
      int retry, result;

      struct monitor_db* monitor = mon->db;
      struct group_db* group;
      struct subgroup_db* subgroup;
      struct control_db* control;
      struct value_db* valued;
      xmlChar* controlname = NULL;
      xmlChar* valuename = NULL;
      
      for (retry = RETRYS; retry; retry--) {
            if ((result = ddcci_readctrl(mon, ctrl, &value, &maximum)) >= 0) 
            {
                  if ((result > 0) || force)
                  {
                        if (monitor) 
                        {
                              /* loop through groups */
                              for (group = monitor->group_list; (group != NULL) && 
                                          (controlname == NULL); group = group->next) 
                              {
                                    /* loop through subgroups inside group */
                                    for (subgroup = group->subgroup_list; (subgroup != NULL); subgroup = subgroup->next) 
                                    {
                                          /* loop through controls inside subgroup */
                                          for (control = subgroup->control_list; (control != NULL); control = control->next) 
                                          {
                                                /* check for control id */
                                                if (control->address == ctrl) 
                                                {
                                                      controlname = control->name;
                                                      /* look for the value */
                                                      for (valued = control->value_list; (valued != NULL); valued = valued->next) {
                                                            if (valued->value == value) {
                                                                  valuename = valued->name;
                                                                  break;
                                                            }
                                                      }
                                                      break;
                                                }
                                          }
                                    }
                              }
                        }
                        if (controlname == NULL) {
                              fprintf(stdout, "%s 0x%02x: %c/%d/%d %c [???]\n", _("Control"),
                                    ctrl, (result > 0) ? '+' : '-', value, maximum, (mon->caps.vcp[ctrl]) ? 'C' : ' ');
                        }
                        else if (valuename == NULL) {
                              fprintf(stdout, "%s 0x%02x: %c/%d/%d %c [%s]\n", _("Control"),
                                    ctrl, (result > 0) ? '+' : '-',  value, maximum, (mon->caps.vcp[ctrl]) ? 'C' : ' ', controlname);
                        }
                        else {
                              fprintf(stdout, "%s 0x%02x: %c/%d/%d %c [%s - %s]\n", _("Control"),
                                    ctrl, (result > 0) ? '+' : '-',  value, maximum, (mon->caps.vcp[ctrl]) ? 'C' : ' ', controlname, valuename);
                        }
                  }
                  break;
            }
      }
}

/* Find the delay we must respect after writing to an address in the database. */
static int find_write_delay(struct monitor* mon, char ctrl) {
      struct monitor_db* monitor = mon->db;
      struct group_db* group;
      struct subgroup_db* subgroup;
      struct control_db* control;
      
      if (monitor)
      {
            /* loop through groups */
            for (group = monitor->group_list; group != NULL; group = group->next)
            {
                  /* loop through subgroups inside group */
                  for (subgroup = group->subgroup_list; subgroup != NULL; subgroup = subgroup->next)
                  {
                        /* loop through controls inside subgroup */
                        for (control = subgroup->control_list; control != NULL; control = control->next)
                        {
                              /* check for control id */
                              if (control->address == ctrl) 
                              {
                                    return control->delay;                          }
                        }
                  }
            }
      }
      return -1;
}

static void usage(char *name)
{
      fprintf(stderr,_(
            "Usage:\n"
            "%s [-b datadir] [-v] [-c] [-d] [-f] [-s] [-r ctrl [-w value]] [-p | dev]\n"
            "\tdev: device, e.g. dev:/dev/i2c-0\n"
            "\t-p : probe I2C devices to find monitor buses\n"
            "\t-c : query capability\n"
            "\t-d : query ctrls 0 - 255\n"
            "\t-r : query ctrl\n"
            "\t-w : value to write to ctrl\n"
            "\t-f : force (avoid validity checks)\n"
            "\t-s : save settings\n"
            "\t-v : verbosity (specify more to increase)\n"
            "\t-b : ddccontrol-db directory (if other than %s)\n"
      ), name, DATADIR);
}

static void check_integrity(char* datadir, char* pnpname) {
      struct monitor_db* mon_db;
      
      printf(_("Checking %s integrity...\n"), "options.xml");
      if (!ddcci_init_db(datadir)) {
            printf(_("[ FAILED ]\n"));
            exit(1);
      }

      printf(_("[ OK ]\n"));
      
      /* Create caps with all controls. */
      char buf2[4];
      char buffer[256*3+25];
      strcpy(buffer, "(vcp(");
      int i;
      for (i = 0; i < 256; i++) {
            snprintf(buf2, 4, "%02x ", i);
            strcat(buffer, buf2);
      }
      strcat(buffer, "))");
      
      struct caps caps;
      ddcci_parse_caps(buffer, &caps, 1);
      
      printf(_("Checking %s integrity...\n"), pnpname);
      if (!(mon_db = ddcci_create_db(pnpname, &caps, 0))) {
            printf(_("[ FAILED ]\n"));
            ddcci_release_db();
            exit(1);
      }
      
      printf(_("[ OK ]\n"));
      
      ddcci_free_db(mon_db);
      
      ddcci_release_db();
      
      exit(0);
}

int main(int argc, char **argv)
{
      int i, retry, ret;
            
      /* filedescriptor and name of device */
      struct monitor mon;
      char *fn;
      
      char *datadir = NULL;
      char *pnpname = NULL; /* pnpname for -i parameter */
      
      /* what to do */
      int dump = 0;
      int ctrl = -1;
      int value = -1;
      int caps = 0;
      int save = 0;
      int force = 0;
      int verbosity = 0;
      int probe = 0;
      
#ifdef HAVE_GETTEXT
      setlocale(LC_ALL, "");
      bindtextdomain(PACKAGE, LOCALEDIR);
      bindtextdomain("ddccontrol-db", LOCALEDIR);
      textdomain(PACKAGE);
#endif
      
      fprintf(stdout,
            _("ddccontrol version %s\n"
            "Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)\n"
            "Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)\n"
            "This program comes with ABSOLUTELY NO WARRANTY.\n"
            "You may redistribute copies of this program under the terms of the GNU General Public License.\n\n"), VERSION);
      
      while ((i=getopt(argc,argv, "hdr:w:csfvpb:i:")) >= 0)
      {
            switch(i) {
            case 'h':
                  usage(argv[0]);
                  exit(1);
                  break;
            case 'b':
                  datadir = optarg;
                  break;
            case 'r':
                  if ((ctrl = strtol(optarg, NULL, 0)) < 0 || (ctrl > 255))
                  {
                        fprintf(stderr,_("'%s' does not seem to be a valid register name\n"), optarg);
                        exit(1);
                  }
                  break;
            case 'w':
                  if (ctrl == -1) {
                        fprintf(stderr,_("You cannot use -w parameter without -r.\n"));
                        exit(1);
                  }
                  if ((value = strtol(optarg, NULL, 0)) < 0 || (value > 65535))
                  {
                        fprintf(stderr,_("'%s' does not seem to be a valid value.\n"), optarg);
                        exit(1);
                  }
                  break;
            case 'c':
                  caps++;
                  break;
            case 'd':
                  dump++;
                  break;
            case 's':
                  save++;
                  break;
            case 'f':
                  force++;
                  break;
            case 'v':
                  verbosity++;
                  break;
            case 'p':
                  probe++;
                  break;
            case 'i': /* Undocumented developer parameter: check integrity of a specific EDID id */
                  pnpname = optarg;
                  break;
            }
      }
      
      ddcci_verbosity(verbosity);
      if (pnpname) {
            check_integrity(datadir, pnpname);
      }
      
      if ((optind == argc) && (!probe)) /* Nor device, nor probe option specified. */
      {
            usage(argv[0]);
            exit(1);
      }
      else if ((optind != argc) && (probe)) /* Device and probe option specified. */
      {
            usage(argv[0]);
            exit(1);
      }
      
      if (!ddcci_init(datadir)) {
            printf(_("Unable to initialize ddcci library.\n"));
            exit(1);
      }
      
      if (probe) {
            fn = NULL;
            
            struct monitorlist* monlist;
            struct monitorlist* current;
            
            monlist = ddcci_probe();
            
            printf(_("Detected monitors :\n"));
            
            current = monlist;
            while (current != NULL)
            {
                  printf(_(" - Device: %s\n"), current->filename);
                  printf(_("   DDC/CI supported: %s\n"), current->supported ? _("Yes") : _("No"));
                  printf(_("   Monitor Name: %s\n"), current->name);
                  printf(_("   Input type: %s\n"), current->digital ? _("Digital") : _("Analog"));
                  
                  if ((!fn) && (current->supported))
                  {
                        printf(_("  (Automatically selected)\n"));
                        fn = malloc(strlen(current->filename)+1);
                        strcpy(fn, current->filename);
                  }
                  
                  current = current->next;
            }
            
            if (fn == NULL) {
                  fprintf(stderr, _(
                        "No monitor supporting DDC/CI available.\n"
                        "If your graphics card need it, please check all the required kernel modules are loaded (i2c-dev, and your framebuffer driver).\n"
                      ));
                  ddcci_release();
                  exit(0);
            }
            
            ddcci_free_list(monlist);
      }
      else {
            fn = argv[optind];
      }
      
      fprintf(stdout, _("Reading EDID and initializing DDC/CI at bus %s...\n"), fn);
      
      if ((ret = ddcci_open(&mon, fn, 0)) < 0) {
            fprintf(stderr, _(
                  "\nDDC/CI at %s is unusable (%d).\n"
                  "If your graphics card need it, please check all the required kernel modules are loaded (i2c-dev, and your framebuffer driver).\n"
                ), fn, ret);
      } else {
            fprintf(stdout, _("\nEDID readings:\n"));
            fprintf(stdout, _("\tPlug and Play ID: %s [%s]\n"), 
                  mon.pnpid, mon.db ? mon.db->name : NULL);
            fprintf(stdout, _("\tInput type: %s\n"), mon.digital ? _("Digital") : _("Analog"));
            
            if (mon.fallback) {
                  /* Put a big warning (in red if we are writing to a terminal). */
                  printf("%s%s\n", isatty(1) ? "\x1B[5;31m" : "", _("=============================== WARNING ==============================="));
                  if (mon.fallback == 1) {
                        printf(_(
                              "There is no support for your monitor in the database, but ddccontrol is\n"
                              "using a generic profile for your monitor's manufacturer. Some controls\n"
                              "may not be supported, or may not work as expected.\n"));
                  }
                  else if (mon.fallback == 2) {
                        printf(_(
                              "There is no support for your monitor in the database, but ddccontrol is\n"
                              "using a basic generic profile. Many controls will not be supported, and\n"
                              "some controls may not work as expected.\n"));
                  }
                  printf(_(
                              "Please update ddccontrol-db, or, if you are already using the latest\n"
                              "version, please send the output of the following command to\n"
                              "ddccontrol-users@lists.sourceforge.net:\n"));
                  printf("\nLANG= LC_ALL= ddccontrol -p -c -d\n\n");
                  printf(_("Thank you.\n"));
                  printf("%s%s\n", _("=============================== WARNING ==============================="), isatty(1) ? "\x1B[0m" : "");
            }
            
            if (caps) {
                  fprintf(stdout, _("\nCapabilities:\n"));
                  
                  for (retry = RETRYS; retry; retry--) {
                        if (ddcci_caps(&mon) >= 0) {
                              fprintf(stdout, _("Raw output: %s\n"), mon.caps.raw_caps);
                              
                              fprintf(stdout, _("Parsed output: \n"));
                              fprintf(stdout, "\tVCP: ");
                              int i;
                              for (i = 0; i < 256; i++) {
                                    if (mon.caps.vcp[i]) {
                                          printf("%02x ", i);
                                    }
                              }
                              printf("\n");
                              printf(_("\tType: "));
                              switch(mon.caps.type) {
                              case lcd:
                                    printf(_("LCD"));
                                    break;
                              case crt:
                                    printf(_("CRT"));
                                    break;
                              case unk:
                                    printf(_("Unknown"));
                                    break;
                              }
                              printf("\n");
                              break;
                        }
                  }
                  
                  if (retry == 0) {
                        fprintf(stderr, _("Capabilities read fail.\n"));
                  }
            }
            
            if (ctrl >= 0) {
                  if (value >= 0) {
                        int delay = find_write_delay(&mon, ctrl);
                        if (delay >= 0) {
                              fprintf(stdout, _("\nWriting 0x%02x, 0x%02x(%d) (%dms delay)...\n"),
                                    ctrl, value, value, delay);
                        }
                        else {
                              fprintf(stdout, _("\nWriting 0x%02x, 0x%02x(%d)...\n"),
                                    ctrl, value, value);
                        }
                        ddcci_writectrl(&mon, ctrl, value, delay);
                  } else {
                        fprintf(stdout, _("\nReading 0x%02x...\n"), ctrl);
                  }
                  
                  dumpctrl(&mon, ctrl, 1);
            }
            
            if (dump) {
                  fprintf(stdout, _("\nControls (valid/current/max) [Description - Value name]:\n"));
                  
                  for (i = 0; i < 256; i++) {
                        dumpctrl(&mon, i, force);
                  }
            }
            else if (ctrl == -1 && caps == 0) 
            {
                  struct monitor_db* monitor = mon.db;
                  struct group_db* group;
                  struct subgroup_db* subgroup;
                  struct control_db* control;
                  struct value_db* valued;
                  
                  if (monitor) {          
                        printf("\n= %s\n", monitor->name);
                        
                        for (group = monitor->group_list; group != NULL; group = group->next) {
                              printf("> %s\n", group->name);
                              
                              for (subgroup = group->subgroup_list; subgroup != NULL; subgroup = subgroup->next) {
                                    printf("\t> %s\n", subgroup->name);
                                    
                                    for (control = subgroup->control_list; control != NULL; control = control->next) {
                                          printf(_("\t\t> id=%s, name=%s, address=%#x, delay=%dms, type=%d\n"), 
                                                control->id, control->name, control->address, control->delay, control->type);
                                          
                                          valued = control->value_list;
                                          if (valued) {
                                                printf(_("\t\t  Possible values:\n"));
                                          }
                                          
                                          for (; valued != NULL; valued = valued->next) {
                                                printf(_("\t\t\t> id=%s - name=%s, value=%d\n"), valued->id, valued->name, valued->value);
                                          }
                                          
                                          for (retry = RETRYS; retry; retry--) {
                                                int result;
                                                unsigned short value, maximum;
                                                
                                                if ((result = ddcci_readctrl(&mon, control->address, &value, &maximum)) >= 0) {
                                                      printf(
                                                            (result > 0) 
                                                                  ? _("\t\t  supported, value=%d, maximum=%d\n")
                                                                  : _("\t\t  not supported, value=%d, maximum=%d\n"), value, maximum);
                                                      break;
                                                }
                                          }
                                    }
                              }
                        }
                  }
            }
            
            if (save) {
                  fprintf(stdout, _("\nSaving settings...\n"));
      
                  ddcci_save(&mon);
            }
      }
      
      ddcci_close(&mon);
      
      if (probe) {
            free(fn);
      }
      
      ddcci_release();
      exit(0);
}

Generated by  Doxygen 1.6.0   Back to index