linux下使用C代码通过一个设备的vend id和dev id找到它的BAR3地址?

#include 
#include 
#include 
#include 

#define VENDOR_ID 0x1234
#define DEVICE_ID 0x5678

// Function to check if a directory entry represents a PCI device with matching vendor and device IDs
int isMatchingDevice(const char *dirPath, int vendorID, int deviceID) {
    char path[PATH_MAX];
    char id[20];
    FILE *file;

    // Generate the path to the device's vendor ID file
    snprintf(path, sizeof(path), "%s/vendor", dirPath);

    // Open the vendor ID file
    file = fopen(path, "r");
    if (file == NULL) {
        return 0; // Error opening file
    }

    // Read the vendor ID from the file
    fgets(id, sizeof(id), file);
    fclose(file);

    // Check if the vendor ID matches
    if (strtoul(id, NULL, 16) != vendorID) {
        return 0; // Vendor ID doesn't match
    }

    // Generate the path to the device's device ID file
    snprintf(path, sizeof(path), "%s/device", dirPath);

    // Open the device ID file
    file = fopen(path, "r");
    if (file == NULL) {
        return 0; // Error opening file
    }

    // Read the device ID from the file
    fgets(id, sizeof(id), file);
    fclose(file);

    // Check if the device ID matches
    if (strtoul(id, NULL, 16) != deviceID) {
        return 0; // Device ID doesn't match
    }

    return 1; // Vendor and device IDs match
}

// Function to find the Base Address Register (BAR3) of a device with matching vendor and device IDs
unsigned long findBAR3(int vendorID, int deviceID) {
    DIR *dir;
    struct dirent *entry;
    char path[PATH_MAX];
    unsigned long bar3 = 0;

    // Open the PCI devices directory
    dir = opendir("/sys/bus/pci/devices");
    if (dir == NULL) {
        perror("Failed to open PCI devices directory");
        return 0;
    }

    // Iterate through each directory entry in the PCI devices directory
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_LNK) {
            // Generate the path to the current device directory
            snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s", entry->d_name);

            // Check if the current device matches the vendor and device IDs
            if (isMatchingDevice(path, vendorID, deviceID)) {
                // Generate the path to the device's BAR3 file
                snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/resource", entry->d_name);

                // Open the device's BAR3 file
                FILE *file = fopen(path, "r");
                if (file == NULL) {
                    perror("Failed to open BAR3 file");
                    break;
                }

                // Read the BAR3 value from the file
                //char value[20];
                //fgets(value, sizeof(value), file);
                //fclose(file);

                 uint64_t bar3 = 0;
               int n = fscanf(file, "%*x%*x%*x\n%*x%*x%*x\n%*x%*x%*x\n%lx", &bar3);//"%*x" is read and skip a hex value,"%\n" is read and skip a line break
               if (n != 1) {
                  perror("Can not get BAR3\n");
                  fclose(file);
                  return -1;
               }
               printf("vend id:0x%0x,deice id:0x%04x,Bar3:0x%lx,d_name:%s\n",vendorID,deviceID,bar3,entry->d_name);

                // Convert the BAR3 value from hexadecimal to unsigned long
                bar3 = strtoul(value, NULL, 16);
                break;
            }
        }
    }

    closedir(dir);

    return bar3;
}

int main() {
    unsigned long bar3 = findBAR3(VENDOR_ID, DEVICE_ID);

    if (bar3 != 0) {
        printf("BAR3 value: 0x%lx\n", bar3);
    } else {
        printf("Device with matching vendor and device IDs not found.\n");
    }

    return 0;
}

让我解释一下 fscanf 函数中 这个格式字符串的含义:

  • %*lx:这个部分表示读取一个十六进制数,并将其忽略(*表示忽略赋值)。实际上我测试后发现%*x也可以读取并忽略一个十六进制数。

  • \n:这个部分表示读取并忽略一个换行符。

  • %lx:这个部分表示读取一个十六进制数并将其赋值给bar3Address变量。

你可能感兴趣的:(linux常用操作,驱动开发,linux驱动开发,linux,linux驱动)