2021-02-18 22:25:36 +01:00
#include "fastfetch.h"
2021-04-09 14:07:05 +02:00
#include <string.h>
2021-02-18 22:25:36 +01:00
2021-04-15 18:59:26 +02:00
#define FF_GPU_MODULE_NAME "GPU"
2021-05-07 17:10:22 +02:00
#define FF_GPU_NUM_FORMAT_ARGS 4
2021-04-03 21:51:50 +02:00
2021-10-19 18:44:59 +02:00
#ifndef FF_HAVE_LIBPCI
void ffPrintGPU ( FFinstance * instance )
{
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "Fastfetch was compiled without libpci support" );
}
#else
#include <dlfcn.h>
#include <pci/pci.h>
2021-05-08 17:18:59 +02:00
static void printGPU ( FFinstance * instance , struct pci_access * pacc , struct pci_dev * dev , FFcache * cache , uint8_t counter , char * ( * ffpci_lookup_name )( struct pci_access * , char * , int , int , ...))
2021-04-03 21:51:50 +02:00
{
2021-02-22 16:52:51 +01:00
char vendor [ 512 ];
2021-05-07 17:10:22 +02:00
vendor [ 0 ] = '\0' ;
2021-02-28 17:38:26 +01:00
ffpci_lookup_name ( pacc , vendor , sizeof ( vendor ), PCI_LOOKUP_VENDOR , dev -> vendor_id , dev -> device_id );
2021-02-18 22:25:36 +01:00
2021-04-15 18:59:26 +02:00
const char * vendorPretty ;
2021-03-19 20:57:07 +01:00
if ( strcasecmp ( vendor , "Advanced Micro Devices, Inc. [AMD/ATI]" ) == 0 )
2021-04-15 18:59:26 +02:00
vendorPretty = "AMD ATI" ;
else if ( strcasecmp ( vendor , "NVIDIA Corporation" ) == 0 )
vendorPretty = "Nvidia" ;
else if ( strcasecmp ( vendor , "Intel Corporation" ) == 0 )
vendorPretty = "Intel" ;
2021-03-19 20:57:07 +01:00
else
2021-04-15 18:59:26 +02:00
vendorPretty = vendor ;
2021-03-19 20:57:07 +01:00
2021-02-22 16:52:51 +01:00
char name [ 512 ];
2021-05-07 17:10:22 +02:00
name [ 0 ] = '\0' ;
2021-02-28 17:38:26 +01:00
ffpci_lookup_name ( pacc , name , sizeof ( name ), PCI_LOOKUP_DEVICE , dev -> vendor_id , dev -> device_id );
2021-02-18 22:25:36 +01:00
2021-05-07 17:10:22 +02:00
FFstrbuf namePretty ;
ffStrbufInitA ( & namePretty , 512 );
ffStrbufAppendS ( & namePretty , name );
ffStrbufSubstrBeforeLastC ( & namePretty , ']' );
ffStrbufSubstrAfterFirstC ( & namePretty , '[' );
2021-04-03 12:14:25 +02:00
FFstrbuf gpu ;
ffStrbufInitA ( & gpu , 128 );
2021-03-19 20:57:07 +01:00
2021-05-07 17:10:22 +02:00
ffStrbufSetF ( & gpu , "%s %s" , vendorPretty , namePretty . chars );
2021-02-22 16:52:51 +01:00
2021-04-15 18:59:26 +02:00
ffPrintAndAppendToCache ( instance , FF_GPU_MODULE_NAME , counter , & instance -> config . gpuKey , cache , & gpu , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , ( FFformatarg []){
{ FF_FORMAT_ARG_TYPE_STRING , vendor },
{ FF_FORMAT_ARG_TYPE_STRING , vendorPretty },
2021-05-07 17:10:22 +02:00
{ FF_FORMAT_ARG_TYPE_STRING , name },
{ FF_FORMAT_ARG_TYPE_STRBUF , & namePretty }
2021-04-15 18:59:26 +02:00
});
2021-04-03 21:51:50 +02:00
2021-03-19 20:57:07 +01:00
ffStrbufDestroy ( & gpu );
2021-05-07 17:10:22 +02:00
ffStrbufDestroy ( & namePretty );
2021-02-18 22:25:36 +01:00
}
2021-02-27 18:30:05 +01:00
void ffPrintGPU ( FFinstance * instance )
2021-02-18 22:25:36 +01:00
{
2021-04-15 18:59:26 +02:00
if ( ffPrintFromCache ( instance , FF_GPU_MODULE_NAME , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS ))
return ;
2021-04-03 21:51:50 +02:00
2021-05-16 15:10:15 +02:00
const char * pciLibName = instance -> config . libPCI . length == 0 ? "libpci.so" : instance -> config . libPCI . chars ;
void * pci = dlopen ( pciLibName , RTLD_LAZY );
2021-02-28 17:38:26 +01:00
if ( pci == NULL )
{
2021-05-16 15:10:15 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlopen( \" %s \" , RTLD_LAZY) == NULL" , pciLibName );
2021-02-28 17:38:26 +01:00
return ;
}
struct pci_access * ( * ffpci_alloc )() = dlsym ( pci , "pci_alloc" );
if ( ffpci_alloc == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_alloc \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
void ( * ffpci_init )( struct pci_access * ) = dlsym ( pci , "pci_init" );
if ( ffpci_init == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_init \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
void ( * ffpci_scan_bus )( struct pci_access * ) = dlsym ( pci , "pci_scan_bus" );
if ( ffpci_scan_bus == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_init \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
int ( * ffpci_fill_info )( struct pci_dev * , int ) = dlsym ( pci , "pci_fill_info" );
if ( ffpci_fill_info == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_fill_info \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
char * ( * ffpci_lookup_name )( struct pci_access * , char * , int , int , ...) = dlsym ( pci , "pci_lookup_name" );
if ( ffpci_lookup_name == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_lookup_name \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
void ( * ffpci_cleanup )( struct pci_access * ) = dlsym ( pci , "pci_cleanup" );
if ( ffpci_cleanup == NULL )
{
2021-04-05 23:42:07 +02:00
dlclose ( pci );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "dlsym(pci, \" pci_cleanup \" ) == NULL" );
2021-02-28 17:38:26 +01:00
return ;
}
2021-05-08 17:18:59 +02:00
struct pci_access * pacc = ffpci_alloc ();
ffpci_init ( pacc );
ffpci_scan_bus ( pacc );
FFlist devices ;
ffListInitA ( & devices , sizeof ( struct pci_dev * ), 4 );
2021-02-18 22:25:36 +01:00
2021-04-15 18:59:26 +02:00
FFcache cache ;
ffCacheOpenWrite ( instance , FF_GPU_MODULE_NAME , & cache );
2021-05-08 17:18:59 +02:00
struct pci_dev * dev ;
2021-02-18 22:25:36 +01:00
for ( dev = pacc -> devices ; dev ; dev = dev -> next )
{
2021-02-28 17:38:26 +01:00
ffpci_fill_info ( dev , PCI_FILL_IDENT | PCI_FILL_CLASS );
2021-02-18 22:25:36 +01:00
char class [ 1024 ];
2021-02-28 17:38:26 +01:00
ffpci_lookup_name ( pacc , class , sizeof ( class ), PCI_LOOKUP_CLASS , dev -> device_class );
2021-02-18 22:25:36 +01:00
if (
2021-02-27 21:10:27 +01:00
strcasecmp ( "VGA compatible controller" , class ) == 0 ||
strcasecmp ( "3D controller" , class ) == 0 ||
2021-05-08 17:18:59 +02:00
strcasecmp ( "Display controller" , class ) == 0
) * ( struct pci_dev ** ) ffListAdd ( & devices ) = dev ;
2021-02-18 22:25:36 +01:00
}
2021-03-03 19:59:39 +01:00
2021-05-08 17:18:59 +02:00
for ( uint32_t i = 0 ; i < devices . length ; i ++ )
printGPU ( instance , pacc , * ( struct pci_dev ** ) ffListGet ( & devices , i ), & cache , devices . length == 1 ? 0 : i + 1 , ffpci_lookup_name );
2021-04-03 21:51:50 +02:00
2021-05-08 17:18:59 +02:00
if ( devices . length == 0 )
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_GPU_MODULE_NAME , 0 , & instance -> config . gpuKey , & instance -> config . gpuFormat , FF_GPU_NUM_FORMAT_ARGS , "No GPU found" );
2021-05-08 17:18:59 +02:00
ffCacheClose ( & cache );
ffListDestroy ( & devices );
ffpci_cleanup ( pacc );
dlclose ( pci );
2021-03-27 18:14:19 +01:00
}
2021-10-19 18:44:59 +02:00
#endif