Пример #1
0
static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0, int idx)
{
    XConfigScreenPtr screen = nvalloc(sizeof(XConfigScreenRec));
    
    screen->identifier = nvasprintf("%s (%d)", screen0->identifier, idx);
    
    screen->device = clone_device(screen0->device, idx);
    screen->device_name = nvstrdup(screen->device->identifier);
    
    screen->monitor = screen0->monitor;
    screen->monitor_name = nvstrdup(screen0->monitor_name);
    
    screen->defaultdepth = screen0->defaultdepth;
    
    screen->displays = clone_display_list(screen0->displays);
    
    screen->options = xconfigOptionListDup(screen0->options);
    if (screen0->comment) screen->comment = nvstrdup(screen0->comment);

    /* insert the new screen after the original screen */

    screen->next = screen0->next;
    screen0->next = screen;

    return screen;
    
} /* clone_screen() */
Пример #2
0
static void create_adjacencies(Options *op, XConfigPtr config,
                               XConfigLayoutPtr layout)
{
    XConfigAdjacencyPtr adj, prev_adj;
    XConfigScreenPtr screen;
    int i;

    i = 0;
    prev_adj = NULL;
    
    for (screen = config->screens; screen; screen = screen->next) {
        
        adj = nvalloc(sizeof(XConfigAdjacencyRec));
        
        adj->scrnum = i;
        adj->screen_name = nvstrdup(screen->identifier);
        adj->screen = screen;
        
        if (prev_adj) {
            prev_adj->next = adj;
        } else {
            layout->adjacencies = adj;
        }
        
        prev_adj = adj;
        i++;
    }
    
    xconfigGenerateAssignScreenAdjacencies(layout);
    
} /* create_adjacencies() */
Пример #3
0
void *nvrealloc(void *ptr, size_t size)
{
    void *m;

    if (ptr == NULL) return nvalloc(size);

    m = realloc(ptr, size);
    if (!m) {
        fprintf(stderr, "%s: memory re-allocation failure (%s)! \n",
                PROGRAM_NAME, strerror(errno));
        exit(1);
    }
    return m;

} /* nvrealloc() */
Пример #4
0
/*
 * Read from the given FILE stream until a newline, EOF, or nul
 * terminator is encountered, writing data into a growable buffer.
 * The eof parameter is set to TRUE when EOF is encountered.  In all
 * cases, the returned string is null-terminated.
 *
 * XXX this function will be rather slow because it uses fgetc() to
 * pull each character off the stream one at a time; this is done so
 * that each character can be examined as it's read so that we can
 * appropriately deal with EOFs and newlines.  A better implementation
 * would use fgets(), but that would still require us to parse each
 * read line, checking for newlines or guessing if we hit an EOF.
 */
char *fget_next_line(FILE *fp, int *eof)
{
    char *buf = NULL, *tmpbuf;
    char *c = NULL;
    int len = 0, buflen = 0;
    int ret;

    const int __fget_next_line_len = 32;

    if (eof) {
        *eof = FALSE;
    }

    while (1) {
        if (buflen == len) { /* buffer isn't big enough -- grow it */
            buflen += __fget_next_line_len;
            tmpbuf = nvalloc(buflen);
            if (buf) {
                memcpy(tmpbuf, buf, len);
                nvfree(buf);
            }
            buf = tmpbuf;
            c = buf + len;
        }

        ret = fgetc(fp);

        if ((ret == EOF) && (eof)) {
            *eof = TRUE;
        }

        if ((ret == EOF) || (ret == '\n') || (ret == '\0')) {
            *c = '\0';
            return buf;
        }

        *c = (char) ret;

        len++;
        c++;

    } /* while (1) */

    return NULL; /* should never get here */
}
Пример #5
0
static XConfigDisplayPtr clone_display_list(XConfigDisplayPtr display0)
{
    XConfigDisplayPtr d = NULL, prev = NULL, head = NULL;
    
    while (display0) {
        d = nvalloc(sizeof(XConfigDisplayRec));
        memcpy(d, display0, sizeof(XConfigDisplayRec));
        if (display0->visual) d->visual = nvstrdup(display0->visual);
        if (display0->comment) d->comment = nvstrdup(display0->comment);
        d->options = xconfigOptionListDup(display0->options);
        d->next = NULL;
        if (prev) prev->next = d;
        if (!head) head = d;
        prev = d;
        display0 = display0->next;
    }
    
    return head;
    
} /* clone_display_list() */
Пример #6
0
void ctk_help_data_list_prepend(GList **list,
                                const gchar *label,
                                const gchar *help_text,
                                const gchar *extended_help_text)
{
    CtkHelpDataItem *item;

    if (!label || !help_text) {
        return;
    }

    item = nvalloc(sizeof(CtkHelpDataItem));

    item->label = nvstrdup(label);
    item->help_text = nvstrdup(help_text);
    item->extended_help_text = extended_help_text ?
                               nvstrdup(extended_help_text) : NULL;

    *list = g_list_prepend(*list, item);
}
Пример #7
0
char *nvstrcat(const char *str, ...)
{
    const char *s;
    char *result;
    size_t len;
    va_list ap;
  
    /* walk the varargs to compute the length of the result string */

    va_start(ap, str);

    for (s = str, len = 1; s; s = va_arg(ap, char *)) {
        len += strlen(s);
    }

    va_end(ap);

    /* allocate the result string */

    result = nvalloc(len);
    if (!result)
        return result;
    result[0] = '\0';
    
    /* concatenate the input strings, writing into the result string */
    
    va_start(ap, str);

    for (s = str; s; s = va_arg(ap, char *)) {
        strcat(result, s);
    }

    va_end(ap);
    
    return result;
} /* nvstrcat() */
Пример #8
0
static XConfigDevicePtr clone_device(XConfigDevicePtr device0, int idx)
{
    XConfigDevicePtr device;

    device = nvalloc(sizeof(XConfigDeviceRec));
    
    device->identifier = nvasprintf("%s (%d)", device0->identifier, idx);
    
    if (device0->vendor)  device->vendor  = nvstrdup(device0->vendor);
    if (device0->board)   device->board   = nvstrdup(device0->board);
    if (device0->chipset) device->chipset = nvstrdup(device0->chipset);
    if (device0->busid)   device->busid   = nvstrdup(device0->busid);
    if (device0->card)    device->card    = nvstrdup(device0->card);
    if (device0->driver)  device->driver  = nvstrdup(device0->driver);
    if (device0->ramdac)  device->ramdac  = nvstrdup(device0->ramdac);
    if (device0->comment) device->comment = nvstrdup(device0->comment);

    /* these are needed for multiple X screens on one GPU */

    device->screen = idx;
    device0->screen = 0;

    device->chipid = -1;
    device->chiprev = -1;
    device->irq = -1;

    device->options = xconfigOptionListDup(device0->options);
    
    /* insert the new device after the original device */
    
    device->next = device0->next;
    device0->next = device;

    return device;
    
} /* clone_device() */
Пример #9
0
/*
 * clean_screen_list() - Used by enable_separate_x_screens and
 * disable_separate_x_screens. Given the array screen_list and the config
 * pointer, this function will leave only one screen per different busid in both
 * screen_list array and config->screens list (i.e all the resulting screens in
 * screen_list and config->screens will have an unique busid).
 */
static void clean_screen_list(XConfigScreenPtr *screen_list,
                              XConfigPtr config,
                              int nscreens)
{
    int i, j;
    int *bus, *slot, scratch;

    /* trim out duplicates and get the bus ids*/

    bus = nvalloc(sizeof(int) * nscreens);
    slot = nvalloc(sizeof(int) * nscreens);

    for (i = 0; i < nscreens; i++) {
        bus[i] = -1;
    }
    
    for (i = 0; i < nscreens; i++) {
        if (!screen_list[i] || (bus[i] == -1 &&
            !xconfigParsePciBusString(screen_list[i]->device->busid,
                                      &bus[i], &slot[i], &scratch))) {
            continue;
        }

        for (j = i+1; j < nscreens; j++) {
            if (!screen_list[j] || (bus[j] == -1 &&
                !xconfigParsePciBusString(screen_list[j]->device->busid,
                                          &bus[j], &slot[j], &scratch))) {
                continue;
            }

            if ((bus[i] == bus[j]) && (slot[i] == slot[j])) {
                screen_list[j] = NULL;
            }
        }
    }

    /*
     * for every screen in the screen list, scan through all
     * screens; if any screen, other than *this* screen has the same
     * busid, remove it
     */
    
    for (i = 0; i < nscreens; i++) {
        XConfigScreenPtr screen, prev;
        int bus0, slot0;

        if (!screen_list[i]) {
            continue;
        }

        screen = config->screens;
        prev = NULL;
        
        while (screen) {
            if (screen_list[i] == screen) {
                goto next_screen;
            }
            if (!screen->device) {
                goto next_screen;
            }
            if (!screen->device->busid) {
                goto next_screen;
            }
            if (!xconfigParsePciBusString(screen->device->busid,
                                          &bus0, &slot0, &scratch)) {
                goto next_screen;
            }
            
            if ((bus[i] == bus0) && (slot[i] == slot0)) {
                XConfigScreenPtr next;

                if (prev) {
                    prev->next = screen->next;
                }
                else {
                    config->screens = screen->next;
                }

                next = screen->next;
                screen->next = NULL;
                xconfigFreeScreenList(&screen);
                screen = next;
            }
            else {
                
            next_screen:
                
                prev = screen;
                screen = screen->next;
            }
        }

        screen_list[i]->device->screen = -1;
    }
}
Пример #10
0
static int enable_separate_x_screens(Options *op, XConfigPtr config,
                                     XConfigLayoutPtr layout)
{
    XConfigScreenPtr screen, *screenlist = NULL;
    XConfigAdjacencyPtr adj;
    int* screens_to_clone = NULL;

    int i, nscreens = 0;
    int have_busids;
    
    /* step 1: build the list of screens that are candidate to be cloned */
    
    if (op->screen) {
        screen = xconfigFindScreen(op->screen, config->screens);
        if (!screen) {
            nv_error_msg("Unable to find screen '%s'.", op->screen);
            return FALSE;
        }
        
        screenlist = nvalloc(sizeof(XConfigScreenPtr));
        screenlist[0] = screen;
        nscreens = 1;
        
    } else {
        for (adj = layout->adjacencies; adj; adj = adj->next) {
            nscreens++;
            screenlist = realloc(screenlist,
                                 sizeof(XConfigScreenPtr) * nscreens);
            
            screenlist[nscreens-1] = adj->screen;
        }
    }
    
    if (!nscreens) return FALSE;
    
    /* step 2: do all screens in the list have a bus ID? */
    
    have_busids = TRUE;
    
    for (i = 0; i < nscreens; i++) {
        if (screenlist[i] &&
            screenlist[i]->device &&
            screenlist[i]->device->busid) {
            // this screen has a busid
        } else {
            have_busids = FALSE;
            break;
        }
    }
    
    /*
     * if not everyone has a bus id, then let's assign bus ids to all
     * the screens; XXX what if _some_ already have busids?  Too bad,
     * we're going to reassign all of them.
     */
    
    if (!have_busids) {
        DevicesPtr pDevices;
        
        pDevices = find_devices(op);
        if (!pDevices) {
            nv_error_msg("Unable to determine number or location of "
                         "GPUs in system; cannot "
                         "honor '--separate-x-screens' option.");
            return FALSE;
        }
        
        for (i = 0; i < nscreens; i++) {
            if (i >= pDevices->nDevices) {
                /*
                 * we have more screens than GPUs, this screen is no
                 * longer a candidate
                 */
                screenlist[i] = NULL;
                continue;
            }
            
            screenlist[i]->device->busid = nvalloc(32);
            xconfigFormatPciBusString(screenlist[i]->device->busid, 32,
                                      pDevices->devices[i].dev.domain,
                                      pDevices->devices[i].dev.bus,
                                      pDevices->devices[i].dev.slot, 0);

            screenlist[i]->device->board = nvstrdup(pDevices->devices[i].name);
        }

        free_devices(pDevices);
    }

    /* step 3 */
    clean_screen_list(screenlist, config, nscreens);
    
    /* step 4 */
    screens_to_clone = get_screens_to_clone(op, screenlist, nscreens);
    
    /* step 5: clone each eligible screen */
    
    for (i = 0; i < nscreens; i++) {
        if (!screenlist[i]) continue;

        while (--screens_to_clone[i] > 0) {
            clone_screen(screenlist[i], screens_to_clone[i]);
        }
    }

    nvfree(screens_to_clone);
    
    /* step 6: wipe the existing adjacencies and recreate them */
    
    xconfigFreeAdjacencyList(&layout->adjacencies);
    
    create_adjacencies(op, config, layout);

    /* free unused device and monitor sections */
    
    free_unused_devices(op, config);
    free_unused_monitors(op, config);

    /* free stuff */

    free(screenlist);

    return TRUE;

} /* enable_separate_x_screens() */
Пример #11
0
/*
 * get_screens_to_clone() - try to detect automatically how many heads has each
 * device in order to use that number to create more than two separate X
 * screens. If the user specifies the option --num-x-screens <quantity>, that
 * value is used. If neither the user specifies the quantity or the number of
 * heads can be detected automatically, it uses 2 heads (the standard
 * behavior). This function returns an array of size nscreens with the number
 * of screens to clone per screen candidate. The caller is responsible of
 * freeing the memory of that array.
 */
static int* get_screens_to_clone(Options *op,
                                 const XConfigScreenPtr *screen_candidates,
                                 int nscreens)
{
    DevicesPtr pDevices;
    int *screens_to_clone, *supported_screens;
    int i, j, devs_found;

    screens_to_clone = nvalloc(nscreens * sizeof(int));
    supported_screens = nvalloc(nscreens * sizeof(int));

    /* Detect the number of supported screens per screen candidate */
    devs_found = FALSE;
    pDevices = find_devices(op);
    if (pDevices) {
        for (i = 0; i < nscreens; i++) {
            int bus, slot, scratch;

            if (!screen_candidates[i]) {
                continue;
            }

            /* parse the bus id for this candidate screen */
            if (!xconfigParsePciBusString(screen_candidates[i]->device->busid,
                                          &bus, &slot, &scratch)) {
                continue;
            }

            for (j = 0; j < pDevices->nDevices; j++) {
                if ((pDevices->devices[j].dev.bus == bus) &&
                    (pDevices->devices[j].dev.slot == slot)) {

                    if (pDevices->devices[j].crtcs > 0) {
                        supported_screens[i] = pDevices->devices[j].crtcs;
                    }
                    break;
                }
            }
        }
        free_devices(pDevices);
        devs_found = TRUE;
    }

    /* If user has defined a number of screens per GPU, use that value */
    if (op->num_x_screens > 0) {
        for (i = 0; i < nscreens; i++) {
            if (!screen_candidates[i]) {
                continue;
            }

            /* Print error when user specifies more X screens than supported */
            if (devs_found && op->num_x_screens > supported_screens[i]) {
                nv_warning_msg("Number of X screens specified is higher than the "
                               "supported quantity (%d)", supported_screens[i]);
            }

            screens_to_clone[i] = op->num_x_screens;
        }

        goto done;
    }

    for (i = 0; i < nscreens; i++) {
        if (screen_candidates[i]) {
            if (devs_found) {
                /* If devices found, use the supported screens number */
                screens_to_clone[i] = supported_screens[i];
            }
            else {
                /* Default behavior (2 heads per GPU) */
                screens_to_clone[i] = 2;
            }
        }
    }

done:
    nvfree(supported_screens);
    return screens_to_clone;
}
Пример #12
0
static Package *parse_manifest (Options *op)
{
    char *buf, *c, *tmpstr;
    int line;
    int fd, ret, len = 0;
    struct stat stat_buf;
    Package *p;
    char *manifest = MAP_FAILED, *ptr;
    int opengl_files_packaged = FALSE;

    p = (Package *) nvalloc(sizeof (Package));

    /* open the manifest file */

    if ((fd = open(".manifest", O_RDONLY)) == -1) {
        ui_error(op, "No package found for installation.  Please run "
                 "this utility with the '--help' option for usage "
                 "information.");
        goto fail;
    }
    
    if (fstat(fd, &stat_buf) == -1) goto cannot_open;
    
    len = stat_buf.st_size;

    manifest = mmap(0, len, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
    if (manifest == MAP_FAILED) goto cannot_open;
    
    /* the first line is the description */

    line = 1;
    p->description = get_next_line(manifest, &ptr, manifest, len);
    if (!p->description) goto invalid_manifest_file;
    
    /* the second line is the version */
    
    line++;
    p->version = get_next_line(ptr, &ptr, manifest, len);
    if (!p->version) goto invalid_manifest_file;
    
    /* Ignore the third line */

    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));

    /* the fourth line is the list of kernel modules. */

    line++;
    tmpstr = get_next_line(ptr, &ptr, manifest, len);
    if (parse_kernel_modules_list(p, tmpstr) == 0) {
        goto invalid_manifest_file;
    }
    nvfree(tmpstr);

    /*
     * set the default value of excluded_kernel_modules to an empty, heap
     * allocated string so that it can be freed and won't prematurely end
     * an nvstrcat()ed string when unset.
     */

    p->excluded_kernel_modules = nvstrdup("");

    /*
     * ignore the fifth and sixth lines
     */

    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));
    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));

    /* the seventh line is the kernel module build directory */

    line++;
    p->kernel_module_build_directory = get_next_line(ptr, &ptr, manifest, len);
    if (!p->kernel_module_build_directory) goto invalid_manifest_file;
    remove_trailing_slashes(p->kernel_module_build_directory);

    /*
     * the eigth line is the directory containing precompiled kernel
     * interfaces
     */

    line++;
    p->precompiled_kernel_interface_directory =
        get_next_line(ptr, &ptr, manifest, len);
    if (!p->precompiled_kernel_interface_directory)
        goto invalid_manifest_file;
    remove_trailing_slashes(p->precompiled_kernel_interface_directory);

    /* the rest of the file is file entries */

    line++;
    
    for (; (buf = get_next_line(ptr, &ptr, manifest, len)); line++) {
        char *flag = NULL;
        PackageEntry entry;
        int entry_success = FALSE;

        if (buf[0] == '\0') {
            free(buf);
            break;
        }

        /* initialize the new entry */

        memset(&entry, 0, sizeof(PackageEntry));

        /* read the file name and permissions */

        c = buf;

        entry.file = read_next_word(buf, &c);

        if (!entry.file) goto entry_done;

        tmpstr = read_next_word(c, &c);

        if (!tmpstr) goto entry_done;

        /* translate the mode string into an octal mode */

        ret = mode_string_to_mode(op, tmpstr, &entry.mode);

        free(tmpstr);

        if (!ret) goto entry_done;

        /* every file has a type field */

        entry.type = FILE_TYPE_NONE;

        flag = read_next_word(c, &c);
        if (!flag) goto entry_done;

        entry.type = parse_manifest_file_type(flag, &entry.caps);

        if (entry.type == FILE_TYPE_NONE) {
            goto entry_done;
        }

        /* Track whether certain file types were packaged */

        switch (entry.type) {
            case FILE_TYPE_XMODULE_SHARED_LIB:
                op->x_files_packaged = TRUE;
                break;
            default: break;
        }

        /* set opengl_files_packaged if any OpenGL files were packaged */

        if (entry.caps.is_opengl) {
            opengl_files_packaged = TRUE;
        }

        /* some libs/symlinks have an arch field */

        entry.compat_arch = FILE_COMPAT_ARCH_NONE;

        if (entry.caps.has_arch) {
            nvfree(flag);
            flag = read_next_word(c, &c);
            if (!flag) goto entry_done;

            if (strcmp(flag, "COMPAT32") == 0)
                entry.compat_arch = FILE_COMPAT_ARCH_COMPAT32;
            else if (strcmp(flag, "NATIVE") == 0)
                entry.compat_arch = FILE_COMPAT_ARCH_NATIVE;
            else {
                goto entry_done;
            }
        }

        /* if compat32 files are packaged, set compat32_files_packaged */

        if (entry.compat_arch == FILE_COMPAT_ARCH_COMPAT32) {
            op->compat32_files_packaged = TRUE;
        }

        /* some libs/symlinks have a class field */

        entry.tls_class = FILE_TLS_CLASS_NONE;

        if (entry.caps.has_tls_class) {
            nvfree(flag);
            flag = read_next_word(c, &c);
            if (!flag) goto entry_done;

            if (strcmp(flag, "CLASSIC") == 0)
                entry.tls_class = FILE_TLS_CLASS_CLASSIC;
            else if (strcmp(flag, "NEW") == 0)
                entry.tls_class = FILE_TLS_CLASS_NEW;
            else {
                goto entry_done;
            }
        }

        /* some file types have a path field, or inherit their paths */

        if (entry.caps.has_path) {
            entry.path = read_next_word(c, &c);
            if (!entry.path) goto invalid_manifest_file;
        } else if (entry.caps.inherit_path) {
            int i;
            char *path, *depth, *slash;
            const char * const depth_marker = "INHERIT_PATH_DEPTH:";

            depth = read_next_word(c, &c);
            if (!depth ||
                strncmp(depth, depth_marker, strlen(depth_marker)) != 0) {
                goto invalid_manifest_file;
            }
            entry.inherit_path_depth = atoi(depth + strlen(depth_marker));
            nvfree(depth);

            /* Remove the file component from the packaged filename */
            path = entry.path = nvstrdup(entry.file);
            slash = strrchr(path, '/');
            if (slash == NULL) {
                goto invalid_manifest_file;
            }
            slash[1] = '\0';

            /* Strip leading directory components from the path */
            for (i = 0; i < entry.inherit_path_depth; i++) {
                slash = strchr(entry.path, '/');

                if (slash == NULL) {
                    goto invalid_manifest_file;
                }

                entry.path = slash + 1;
            }

            entry.path = nvstrdup(entry.path);
            nvfree(path);
        } else {
            entry.path = NULL;
        }

        /* symlinks have a target */

        if (entry.caps.is_symlink) {
            entry.target = read_next_word(c, &c);
            if (!entry.target) goto invalid_manifest_file;
        } else {
            entry.target = NULL;
        }

        /*
         * as a convenience for later, set the 'name' pointer to
         * the basename contained in 'file' (ie the portion of
         * 'file' without any leading directory components
         */

        entry.name = strrchr(entry.file, '/');
        if (entry.name) entry.name++;

        if (!entry.name) entry.name = entry.file;

        add_package_entry(p,
                          entry.file,
                          entry.path,
                          entry.name,
                          entry.target,
                          entry.dst,
                          entry.type,
                          entry.tls_class,
                          entry.compat_arch,
                          entry.mode);

        entry_success = TRUE;

 entry_done:
        /* clean up */

        nvfree(buf);
        nvfree(flag);
        if (!entry_success) {
            goto invalid_manifest_file;
        }
    }

    /* If no OpenGL files were packaged, we can't install them. Set the
     * no_opengl_files flag so that everything we skip when explicitly
     * excluding OpenGL is also skipped when OpenGL is not packaged. */

    if (!opengl_files_packaged) {
        op->no_opengl_files = TRUE;
    }

    munmap(manifest, len);
    if (fd != -1) close(fd);

    return p;
    
 cannot_open:
    ui_error(op, "Failure opening package's .manifest file (%s).",
             strerror(errno));
    goto fail;

 invalid_manifest_file:

    ui_error(op, "Invalid .manifest file; error on line %d.", line);
    goto fail;

 fail:
    free_package(p);
    if (manifest != MAP_FAILED) munmap(manifest, len);
    if (fd != -1) close(fd);
    return NULL;
       
} /* parse_manifest() */
Пример #13
0
NvCtrlAttributeHandle *NvCtrlAttributeInit(Display *dpy, int target_type,
                                           int target_id,
                                           unsigned int subsystems)
{
    NvCtrlAttributePrivateHandle *h = NULL;

    h = nvalloc(sizeof (NvCtrlAttributePrivateHandle));

    /* initialize the display and screen to the parameter values */

    h->dpy = dpy;
    h->target_type = target_type;
    h->target_id = target_id;

    /* initialize the NV-CONTROL attributes; give up if this fails */

    if (subsystems & NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM) {
        h->nv = NvCtrlInitNvControlAttributes(h);
        if (!h->nv) goto failed;
    }

    /*
     * initialize X Screen specific attributes for X Screen
     * target types.
     */

    if (target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) {

        /*
         * initialize the XF86VidMode attributes; it is OK if this
         * fails
         */
        
        if (subsystems & NV_CTRL_ATTRIBUTES_XF86VIDMODE_SUBSYSTEM) {
            h->vm = NvCtrlInitVidModeAttributes(h);
        }
        
        /*
         * initialize the XVideo extension and attributes; it is OK if
         * this fails
         */
        
        if (subsystems & NV_CTRL_ATTRIBUTES_XVIDEO_SUBSYSTEM) {
            h->xv = NvCtrlInitXvAttributes(h);
        }
        
        /*
         * initialize the GLX extension and attributes; it is OK if
         * this fails
         */
        
        if (subsystems & NV_CTRL_ATTRIBUTES_GLX_SUBSYSTEM) {
            h->glx = NvCtrlInitGlxAttributes(h);
        }
    } /* X Screen target type attribute subsystems */

    /*
     * initialize the XRandR extension and attributes; this does not
     * require an X screen and it is OK if this fails
     */
    if (subsystems & NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM) {
        h->xrandr = NvCtrlInitXrandrAttributes(h);
    }

    return (NvCtrlAttributeHandle *) h;

 failed:
    if (h) free (h);
    return NULL;

} /* NvCtrlAttributeInit() */
Пример #14
0
static int parse_config_property(const char *file, const char *line, ConfigProperties *conf)
{
    char *no_spaces, *s;
    char *locale;
    ConfigPropertiesTableEntry *t;
    char *timer, *token;
    TimerConfigProperty *c = NULL;
    int interval;
    int ret = NV_FALSE;
    unsigned int flag;
    
    no_spaces = remove_spaces(line);

    if (!no_spaces) goto done;

    s = strchr(no_spaces, '=');

    if (!s) goto done;

    *s = '\0';
    
    if (nv_strcasecmp(no_spaces, "RcFileLocale")) {
        locale = ++s;
        if (setlocale(LC_NUMERIC, locale) == NULL) {
            nv_warning_msg("Error parsing configuration file '%s': could "
                           "not set the specified locale '%s'.",
                           file, locale);
        }
    } else if (nv_strcasecmp(no_spaces, "Timer")) {
        timer = ++s;

        token = strtok(timer, ",");
        if (!token)
            goto done;

        c = nvalloc(sizeof(TimerConfigProperty));

        c->description = replace_characters(token, '_', ' ');

        token = strtok(NULL, ",");
        if (!token)
            goto done;

        if (nv_strcasecmp(token, "Yes")) {
            c->user_enabled = 1;
        } else if (nv_strcasecmp(token, "No")) {
            c->user_enabled = 0;
        } else {
            goto done;
        }

        token = strtok(NULL, ",");
        if (!token)
            goto done;

        parse_read_integer(token, &interval);
        c->interval = interval;

        c->next = conf->timers;
        conf->timers = c;
    } else {
        for (t = configPropertyTable, flag = 0; t->name; t++) {
            if (nv_strcasecmp(no_spaces, t->name)) {
                flag = t->flag;
                break;
            }
        }

        if (!flag) goto done;

        s++;

        if (nv_strcasecmp(s, "yes")) {
            conf->booleans |= flag;
        } else if (nv_strcasecmp(s, "no")) {
            conf->booleans &= ~flag;
        } else {
            goto done;
        }
    }
    
    ret = NV_TRUE;

 done:

    if ((ret != NV_TRUE) && c) {
        if (c->description)
            free(c->description);
        free(c);
    }

    if (no_spaces) free(no_spaces);
    return ret;
    
} /* parse_config_property() */
Пример #15
0
static ParsedAttributeWrapper *parse_config_file(char *buf, const char *file,
                                                 const int length,
                                                 ConfigProperties *conf)
{
    int line, has_data, current_tmp_len, len, n, ret;
    char *cur, *c, *comment, *tmp;
    ParsedAttributeWrapper *w;
    
    cur = buf;
    line = 1;
    current_tmp_len = 0;
    n = 0;
    w = NULL;
    tmp = NULL;

    while (cur) {
        c = cur;
        comment = NULL;
        has_data = NV_FALSE;;
        
        while (((c - buf) < length) &&
               (*c != '\n') &&
               (*c != '\0')) {
            if (comment) { c++; continue; }
            if (*c == '#') { comment = c; continue; }
            if (!isspace(*c)) has_data = NV_TRUE;
            c++;
        }
        
        if (has_data) {
            if (!comment) comment = c;
            len = comment - cur;
            
            /* grow the tmp buffer if it's too small */
            
            if (len >= current_tmp_len) {
                current_tmp_len = len + 1;
                if (tmp) {
                    free(tmp);
                }
                tmp = nvalloc(sizeof(char) * current_tmp_len);
            }

            strncpy (tmp, cur, len);
            tmp[len] = '\0';

            /* first, see if this line is a config property */

            if (!parse_config_property(file, tmp, conf)) {
                
                w = nvrealloc(w, sizeof(ParsedAttributeWrapper) * (n+1));
            
                ret = nv_parse_attribute_string(tmp,
                                                NV_PARSER_ASSIGNMENT,
                                                &w[n].a);
                if (ret != NV_PARSER_STATUS_SUCCESS) {
                    nv_error_msg("Error parsing configuration file '%s' on "
                                 "line %d: '%s' (%s).",
                                 file, line, tmp, nv_parse_strerror(ret));
                    goto failed;
                }
            
                w[n].line = line;
                n++;
            }
        }

        if (((c - buf) >= length) || (*c == '\0')) cur = NULL;
        else cur = c + 1;

        line++;
    }
    free(tmp);
    /* mark the end of the array */

    w = nvrealloc(w, sizeof(ParsedAttributeWrapper) * (n+1));
    w[n].line = -1;
    
    return w;

 failed:
    if (w) free(w);
    free(tmp);
    return NULL;

} /* parse_config_file() */
Пример #16
0
DevicesPtr find_devices(Options *op)
{
    DevicesPtr pDevices = NULL;
    DisplayDevicePtr pDisplayDevice;
    int i, j, n, count = 0;
    unsigned int mask, bit;
    DeviceRec tmpDevice;
    NvCfgPciDevice *devs = NULL;
    NvCfgBool is_primary_device;
    NvCfgBool ret;
    char *lib_path;
    void *lib_handle;

    NvCfgBool (*__getDevices)(int *n, NvCfgDevice **devs);
    NvCfgBool (*__openDevice)(int bus, int slot, NvCfgDeviceHandle *handle);
    NvCfgBool (*__getPciDevices)(int *n, NvCfgPciDevice **devs);
    NvCfgBool (*__openPciDevice)(int domain, int bus, int slot, int function,
                                 NvCfgDeviceHandle *handle);
    NvCfgBool (*__getNumCRTCs)(NvCfgDeviceHandle handle, int *crtcs);
    NvCfgBool (*__getProductName)(NvCfgDeviceHandle handle, char **name);
    NvCfgBool (*__getDisplayDevices)(NvCfgDeviceHandle handle,
                                     unsigned int *display_device_mask);
    NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle,
                           unsigned int display_device,
                           NvCfgDisplayDeviceInformation *info);
    NvCfgBool (*__isPrimaryDevice)(NvCfgDeviceHandle handle,
                                  NvCfgBool *is_primary_device);
    NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle);
    NvCfgBool (*__getDeviceUUID)(NvCfgDeviceHandle handle, char **uuid);
    
    /* dlopen() the nvidia-cfg library */
    
#define __LIB_NAME "libnvidia-cfg.so.1"

    if (op->nvidia_cfg_path) {
        lib_path = nvstrcat(op->nvidia_cfg_path, "/", __LIB_NAME, NULL);
    } else {
        lib_path = strdup(__LIB_NAME);
    }
    
    lib_handle = dlopen(lib_path, RTLD_NOW);
    
    nvfree(lib_path);
    
    if (!lib_handle) {
        nv_warning_msg("error opening %s: %s.", __LIB_NAME, dlerror());
        return NULL;
    }
    
#define __GET_FUNC(proc, name)                                        \
    (proc) = dlsym(lib_handle, (name));                               \
    if (!(proc)) {                                                    \
        nv_warning_msg("error retrieving symbol %s from %s: %s",      \
                       (name), __LIB_NAME, dlerror());                \
        dlclose(lib_handle);                                          \
        return NULL;                                                  \
    }

    /* required functions */
    __GET_FUNC(__getDevices, "nvCfgGetDevices");
    __GET_FUNC(__openDevice, "nvCfgOpenDevice");
    __GET_FUNC(__getPciDevices, "nvCfgGetPciDevices");
    __GET_FUNC(__openPciDevice, "nvCfgOpenPciDevice");
    __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs");
    __GET_FUNC(__getProductName, "nvCfgGetProductName");
    __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices");
    __GET_FUNC(__getEDID, "nvCfgGetEDID");
    __GET_FUNC(__closeDevice, "nvCfgCloseDevice");
    __GET_FUNC(__getDeviceUUID, "nvCfgGetDeviceUUID");

    /* optional functions */
    __isPrimaryDevice = dlsym(lib_handle, "nvCfgIsPrimaryDevice");
    
    if (__getPciDevices(&count, &devs) != NVCFG_TRUE) {
        return NULL;
    }

    if (count == 0) return NULL;

    pDevices = nvalloc(sizeof(DevicesRec));
    
    pDevices->devices = nvalloc(sizeof(DeviceRec) * count);

    pDevices->nDevices = count;

    for (i = 0; i < count; i++) {
        
        pDevices->devices[i].dev = devs[i];
        
        if (__openPciDevice(devs[i].domain, devs[i].bus, devs[i].slot, 0,
                            &(pDevices->devices[i].handle)) != NVCFG_TRUE) {
            goto fail;
        }
        
        if (__getNumCRTCs(pDevices->devices[i].handle,
                          &pDevices->devices[i].crtcs) != NVCFG_TRUE) {
            goto fail;
        }

        if (__getProductName(pDevices->devices[i].handle,
                             &pDevices->devices[i].name) != NVCFG_TRUE) {
            /* This call may fail with little impact to the Device section */
            pDevices->devices[i].name = NULL;
        }

        if (__getDeviceUUID(pDevices->devices[i].handle,
                            &pDevices->devices[i].uuid) != NVCFG_TRUE) {
            goto fail;
        }
        if (__getDisplayDevices(pDevices->devices[i].handle, &mask) !=
            NVCFG_TRUE) {
            goto fail;
        }
        
        pDevices->devices[i].displayDeviceMask = mask;

        /* count the number of display devices */
        
        for (n = j = 0; j < 32; j++) {
            if (mask & (1 << j)) n++;
        }
        
        pDevices->devices[i].nDisplayDevices = n;

        if (n) {

            /* allocate the info array of the right size */
            
            pDevices->devices[i].displayDevices =
                nvalloc(sizeof(DisplayDeviceRec) * n);
            
            /* fill in the info array */
            
            for (n = j = 0; j < 32; j++) {
                bit = 1 << j;
                if (!(bit & mask)) continue;
                
                pDisplayDevice = &pDevices->devices[i].displayDevices[n];
                pDisplayDevice->mask = bit;

                if (__getEDID(pDevices->devices[i].handle, bit,
                              &pDisplayDevice->info) != NVCFG_TRUE) {
                    pDisplayDevice->info_valid = FALSE;
                } else {
                    pDisplayDevice->info_valid = TRUE;
                }
                n++;
            }
        } else {
            pDevices->devices[i].displayDevices = NULL;
        }

        if ((i != 0) && (__isPrimaryDevice != NULL) &&
            (__isPrimaryDevice(pDevices->devices[i].handle,
                               &is_primary_device) == NVCFG_TRUE) &&
            (is_primary_device == NVCFG_TRUE)) {
            memcpy(&tmpDevice, &pDevices->devices[0], sizeof(DeviceRec));
            memcpy(&pDevices->devices[0], &pDevices->devices[i], sizeof(DeviceRec));
            memcpy(&pDevices->devices[i], &tmpDevice, sizeof(DeviceRec));
        }
        
        ret = __closeDevice(pDevices->devices[i].handle);
        pDevices->devices[i].handle = NULL;

        if (ret != NVCFG_TRUE) {
            goto fail;
        }
    }
    
    goto done;
    
 fail:

    nv_warning_msg("Unable to use the nvidia-cfg library to query NVIDIA "
                   "hardware.");

    for (i = 0; i < pDevices->nDevices; i++) {
        /* close the opened device */
        if (pDevices->devices[i].handle) {
            __closeDevice(pDevices->devices[i].handle);
        }
    }

    free_devices(pDevices);
    pDevices = NULL;

    /* fall through */

 done:
    
    if (devs) free(devs);
    
    return pDevices;
    
} /* find_devices() */
Пример #17
0
static int disable_separate_x_screens(Options *op, XConfigPtr config,
                                      XConfigLayoutPtr layout)
{
    XConfigScreenPtr screen, *screenlist = NULL;
    XConfigAdjacencyPtr adj;
    
    int i, nscreens = 0;
    
    /* step 1: build the list of screens that are candidate to be de-cloned */
    
    if (op->screen) {
        screen = xconfigFindScreen(op->screen, config->screens);
        if (!screen) {
            nv_error_msg("Unable to find screen '%s'.", op->screen);
            return FALSE;
        }
        
        screenlist = nvalloc(sizeof(XConfigScreenPtr));
        screenlist[0] = screen;
        nscreens = 1;
        
    } else {
        for (adj = layout->adjacencies; adj; adj = adj->next) {
            nscreens++;
            screenlist = realloc(screenlist,
                                 sizeof(XConfigScreenPtr) * nscreens);
            
            screenlist[nscreens-1] = adj->screen;
        }
    }
    
    /*
     * step 2: limit the list to screens that have a BusID; parse the busIDs
     * while we're at it
     */
    
    for (i = 0; i < nscreens; i++) {
        int bus, slot, scratch;
        if (screenlist[i] &&
            screenlist[i]->device &&
            screenlist[i]->device->busid &&
            xconfigParsePciBusString(screenlist[i]->device->busid,
                                     &bus, &slot, &scratch)) {
            // this screen has a valid busid
        } else {
            screenlist[i] = NULL;
        }
    }

    /* step 3 */
    clean_screen_list(screenlist, config, nscreens);
    
    /* step 4: wipe the existing adjacencies and recreate them */
    
    xconfigFreeAdjacencyList(&layout->adjacencies);
    
    create_adjacencies(op, config, layout);

    /* free unused device and monitor sections */
    
    free_unused_devices(op, config);
    free_unused_monitors(op, config);

    /* free stuff */

    free(screenlist);
    
    return TRUE;
    
} /* disable_separate_x_screens() */