static int read_data_list(const char* name, int (*cb)(Connection *,const char *), Connection *conn) { FILE *f; char buf[4096]; f = fopen(name, "r"); if(!f) return -1; while(fgets(buf, sizeof(buf), f)) { xchomp(buf); if(cb(conn, buf) < 0) { fclose(f); return -1; } } fclose(f); return 0; }
/* This function is used to provide a workaround for binary drivers that * don't export their PCI ID's properly. If distros don't end up using this * feature it can and should be removed because the symbol-based resolution * scheme should be the primary one */ static void matchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) { DIR *idsdir; FILE *fp; struct dirent *direntry; char *line = NULL; size_t len; ssize_t read; char path_name[256], vendor_str[5], chip_str[5]; uint16_t vendor, chip; int i, j; idsdir = opendir(PCI_TXT_IDS_PATH); if (!idsdir) return; xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", PCI_TXT_IDS_PATH); direntry = readdir(idsdir); /* Read the directory */ while (direntry) { if (direntry->d_name[0] == '.') { direntry = readdir(idsdir); continue; } len = strlen(direntry->d_name); /* A tiny bit of sanity checking. We should probably do better */ if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { /* We need the full path name to open the file */ strncpy(path_name, PCI_TXT_IDS_PATH, 256); strncat(path_name, "/", 1); strncat(path_name, direntry->d_name, (256 - strlen(path_name) - 1)); fp = fopen(path_name, "r"); if (fp == NULL) { xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); goto end; } /* Read the file */ #ifdef __GLIBC__ while ((read = getline(&line, &len, fp)) != -1) { #else while ((line = fgetln(fp, &len)) != (char *)NULL) { #endif /* __GLIBC __ */ xchomp(line); if (isdigit(line[0])) { strncpy(vendor_str, line, 4); vendor_str[4] = '\0'; vendor = (int)strtol(vendor_str, NULL, 16); if ((strlen(&line[4])) == 0) { chip_str[0] = '\0'; chip = -1; } else { /* Handle trailing whitespace */ if (isspace(line[4])) { chip_str[0] = '\0'; chip = -1; } else { /* Ok, it's a real ID */ strncpy(chip_str, &line[4], 4); chip_str[4] = '\0'; chip = (int)strtol(chip_str, NULL, 16); } } if (vendor == match_vendor && chip == match_chip ) { i = 0; while (matches[i]) { i++; } matches[i] = (char*)xalloc(sizeof(char) * strlen(direntry->d_name) - 3); if (!matches[i]) { xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); goto end; } /* hack off the .ids suffix. This should guard * against other problems, but it will end up * taking off anything after the first '.' */ for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { if (direntry->d_name[j] == '.') { matches[i][j] = '\0'; break; } else { matches[i][j] = direntry->d_name[j]; } } xf86Msg(X_INFO, "Matched %s from file name %s\n", matches[i], direntry->d_name); } } else { /* TODO Handle driver overrides here */ } } fclose(fp); } direntry = readdir(idsdir); } end: xfree(line); closedir(idsdir); } #endif /* __linux__ */ static void listPossibleVideoDrivers(char *matches[], int nmatches) { struct pci_device * info = NULL; struct pci_device_iterator *iter; int i; for (i = 0 ; i < nmatches ; i++) { matches[i] = NULL; } i = 0; #ifdef sun /* Check for driver type based on /dev/fb type and if valid, use it instead of PCI bus probe results */ if (xf86Info.consoleFd >= 0) { struct vis_identifier visid; const char *cp; extern char xf86SolarisFbDev[PATH_MAX]; int iret; SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); if (iret < 0) { int fbfd; fbfd = open(xf86SolarisFbDev, O_RDONLY); if (fbfd >= 0) { SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid)); close(fbfd); } } if (iret < 0) { xf86Msg(X_WARNING, "could not get frame buffer identifier from %s\n", xf86SolarisFbDev); } else { xf86Msg(X_PROBED, "console driver: %s\n", visid.name); /* Special case from before the general case was set */ if (strcmp(visid.name, "NVDAnvda") == 0) { matches[i++] = xnfstrdup("nvidia"); } /* General case - split into vendor name (initial all-caps prefix) & driver name (rest of the string). */ if (strcmp(visid.name, "SUNWtext") != 0) { for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) { /* find end of all uppercase vendor section */ } if ((cp != visid.name) && (*cp != '\0')) { char *driverName = xnfstrdup(cp); char *vendorName = xnfstrdup(visid.name); vendorName[cp - visid.name] = '\0'; matches[i++] = vendorName; matches[i++] = driverName; } } } } #endif #ifdef __sparc__ { char *sbusDriver = sparcDriverName(); if (sbusDriver) matches[i++] = xnfstrdup(sbusDriver); } #endif /* Find the primary device, and get some information about it. */ iter = pci_slot_match_iterator_create(NULL); while ((info = pci_device_next(iter)) != NULL) { if (xf86IsPrimaryPci(info)) { break; } } pci_iterator_destroy(iter); if (!info) { ErrorF("Primary device is not PCI\n"); } #ifdef __linux__ else { matchDriverFromFiles(matches, info->vendor_id, info->device_id); } #endif /* __linux__ */ for (i = 0; (i < nmatches) && (matches[i]); i++) { /* find end of matches list */ } if ((info != NULL) && (i < nmatches)) { i += videoPtrToDriverList(info, &(matches[i]), nmatches - i); } /* Fallback to platform default hardware */ if (i < (nmatches - 1)) { #if defined(__i386__) || defined(__amd64__) || defined(__hurd__) matches[i++] = xnfstrdup("vesa"); #elif defined(__sparc__) && !defined(sun) matches[i++] = xnfstrdup("sunffb"); #endif } /* Fallback to platform default frame buffer driver */ if (i < (nmatches - 1)) { #if !defined(__linux__) && defined(__sparc__) matches[i++] = xnfstrdup("wsfb"); #else matches[i++] = xnfstrdup("fbdev"); #endif } } /* copy a screen section and enter the desired driver * and insert it at i in the list of screens */ static Bool copyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver) { GDevPtr cptr = NULL; xf86ConfigLayout.screens[i].screen = xnfcalloc(1, sizeof(confScreenRec)); if(!xf86ConfigLayout.screens[i].screen) return FALSE; memcpy(xf86ConfigLayout.screens[i].screen, oscreen, sizeof(confScreenRec)); cptr = xcalloc(1, sizeof(GDevRec)); if (!cptr) return FALSE; memcpy(cptr, odev, sizeof(GDevRec)); cptr->identifier = Xprintf("Autoconfigured Video Device %s", driver); cptr->driver = driver; /* now associate the new driver entry with the new screen entry */ xf86ConfigLayout.screens[i].screen->device = cptr; cptr->myScreenSection = xf86ConfigLayout.screens[i].screen; return TRUE; }