How to identify the name (and only the name) of a PCI device?

So for example, I have a PCI ID (vendor:id/1002:1681) and I want to get the device name for it, one way to utilie this is this:

$ lspci -d 1002:1681 -nn
06:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Rembrandt [Radeon 680M] [1002:1681] (rev c7)

Which gives me the name and some more stuff.

But what I need is to isolate it down to just this part: [Radeon 680M] at best or this part Advanced Micro Devices, Inc. [AMD/ATI] Rembrandt [Radeon 680M] at worst.

I preferably want to do this without lspci, and I need a generic way of doing it (e.g. a way to do it for any device, not just this specific device, which means using cut and sed or awk to isolate only the part I need from lspci is not a satisfying option)

Where does lspci find the name and can I use the same method somehow?

So that’s the question, how do I identify a device’s name, and only the name from the PCI ID?

This should help finding the name unless your lspci output contains any different stuff:

lspci -vnn | grep -P 'VGA|3D|Display' | sed -E 's|.*(\[[^]]+\]) \[.*\].*|\1|'

Program sed is capable of finding various strings inside a string (and much more). It uses regular expressions. You can find many parts of a string this way too.

Look for option -i in man lspci.

BTW, option -m is also useful.

1 Like

Thanks; using the -m option I can reliably isolate the name portion in lspci like this

lspci -md 1002:1681 | cut -d '"' -f6

it’ll give me

Rembrandt [Radeon 680M]
or with the nvidia option
GA104 [Geforce RTX 3070 Ti Laptop GPU]

I would prefer the output of the sed approach you provided me with, but it’s not reliable across different hardware.

However reading the man page for the -i option told me that fstab reads the names from /usr/share/hwdata/pci.ids but it’s not a text file, is there any way I can access the data in it without lspci?

That’s weird I can open the ids file with Kate (contains more then 39000 lines).

Have you tried inxi -Fxx ?

OHHH, it is, I used cat on the file and i got a jarbled output but i guess it was just cuz it was too long for cat, and not cuz it was in some weird binary format like is usually the case when that happens.

Yeah now we’re in business, just need to figure out how to parse the file so i can get the correct device name.

In my case, I would do like this :

lspci -mm|grep VGA  
03:00.0 "VGA compatible controller" "Advanced Micro Devices, Inc. [AMD/ATI]" "Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]" -ref -p00 "Sapphire Technology Limited" "Radeon RX 570 Pulse 4GB" 

then with awk :

lspci -mm | grep VGA | awk -F'"' '{print $10}'
Radeon RX 570 Pulse 4GB

(but it’s not accurate since my card has 8GB of memory :grinning_face:)

1 Like

After a lot of pain (awk kills me, and so does any sed more complicated than the basic substitiotn command) I have figured it out.

$ awk "/^1002/{a=1;next}/^....  /{a=0}a" /usr/share/hwdata/pci.ids | sed -n "0,/\s*1681  /s///p"
Rembrandt [Radeon 680M]

I’ve made it go through all my gpus and print their names one by one in the below code sample:

#!/bin/bash

PCI_IDS=$(find /usr/share -maxdepth 2 -name "pci.ids" -print -quit) #Some distros don't store it in the same place.

for CARD in /sys/class/drm/card[0-99]/device;
do
	VENDOR=$(cut -b 3-6 $CARD/vendor)
	ID=$(cut -b 3-6 $CARD/device)

	# First we get all lines between the VENDOR and the next vendor;
	# then we find an exact match to our ID and print only the name; 
	# Then we look for values inside [brackets] and print only those if there are any.
	NAME=$(awk "/^$VENDOR/{a=1;next}/^....  /{a=0}a" $PCI_IDS | sed -n "0,/\s*$ID  /s///p" | awk -F'[][]' '{if ($2) {print $2} else {print $0}}')

	echo $NAME
done

It also has a bunch of safety checks like the sed command will never print more than 1 line, and it uses symbols to represent leading whitespace so all unwanted whitespace will 100% be removed. And the awk at the end that gets the values between brackets will print the full name if it doesn’t find brackets.

For me it outputs:

Geforce RTX 3070 Ti Laptop GPU
Radeon 680M

So there it is, a reliable way that doesn’t rely on lspci to get the names.

Maybe someone better with awk could make this just be the one awk command but awk is extremely confusing to me. I’ve gone online, copied awk commands, pasted them and modified them like a 100 times now and I still cannot make headas or tails of the syntax, damn thing is like an alien language!

I’m curious, does my script work for you? You should be able to run it without any modifications

Your card has some weird dual layer device ID(1da2 e353); if /sys/class/drm/card*/device contains both of those values it should work with your card.

If not I’m curious where the missing number would be found.

Does not work for me unless I change the CardNumber to 0.

(My actual card is card1.)

You should be able to find it rather reliably with something like

find /dev/dri -type c -name 'card[0-9]' -printf "%f\n"

Odd, the CardNumber starts at -1; then gets a +1 for every card found, so on the first loop it should be card0, second loop should be card1 and so on.

Well, yeah, exactly.
There is 1 card, it starts at -1, so with +1 from that single card the numeral becomes 0, card0 does not exist, and no more addition occurs.

Ah I was working with the assumption that the cards would always start from 0, I’ve fixed it now.

./pcidetect                    
Radeon RX 470/480/570/570X/580/580X/590

I see, a technically correct answer but not specific enough.

To get Radeon RX 570 Pulse 4GB we’d need to find these numbers 1da2 e353 but i don’t know where to find them, the 1da2 seems to refer to sapphire, and e353 refers to the specific device, but it seems even with that you’re not guaranteed to get an accurate name.

As you said it says your card is 4GB but it’s 8GB, and many of the options would output results like Nitro+ Radeon RX 570/580/590 or in the worst case Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT]Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT]

It seems liek sapphire reuses their device identifiers a lot.

Radeon RX 470/480/570/570X/580/580X/590 is the AMD identifier for your card. It’s strange that AMD is using one identifier for 2 whole generations of cards (every ellesmere based card) :laughing:

Like this :

grep "1da2 e353" /usr/share/hwdata/pci.ids
		1da2 e353  Radeon RX 570 Pulse 4GB

man pci.ids

No I knew about those, that’s exactly how i found out the exact numbers for your card, the problem is finiding them somewhere in /sys/class/drm/card*/device/ ideally; because the script isn’t meant to know beforehand what card you’ve got, it’s supposed to find out through gathering the vendor and device ids.

Looks like it’s a mess for the RX 570 card :

grep "RX 570 " /usr/share/hwdata/pci.ids
		1458 22f7  Radeon RX 570 Gaming 4G
		1462 341b  Radeon RX 570 Armor 8G OC
		1462 341e  Radeon RX 570 Armor 4G OC
		148c 2379  Radeon RX 570 4G [Red Dragon]
		1da2 e343  Radeon RX 570 Pulse ITX 4GB
		1da2 e353  Radeon RX 570 Pulse 4GB

but vendor and device from my card are 1002:67df and I just noticed there’s a specific amdgpu file :

grep "RX 570 " /usr/share/libdrm/amdgpu.ids
67DF,	C2,	AMD Radeon RX 570 Series
67DF,	C6,	AMD Radeon RX 570 Series
67DF,	EF,	AMD Radeon RX 570 Series

:confused:

That can’t be it, there has to be something else somewhere in /sys/class/drm/card*/device/ that points to 1da2 e353 maybe a subvendor and subdevice?

I tinnk I figured out where

If you do

cat /sys/class/drm/card*/device/uevent

Does it show it?

I think it might be buried in the MODALIAS somewhere

Yes.

PCI_SUBSYS_ID=1DA2:E353