# Accessing hardware information



## j4ck (Jan 13, 2014)

I'm trying to access information from cards, e.g. a NIC's serial number. How can I read this information pragmatically? I'm using C/C++ as programming language. Any experiences on doing this?

Thanks in advance.


----------



## trh411 (Jan 13, 2014)

*Re: Accessing hardware informations*

If the NICs are PCI devices and if the serial number is stored in VPD, you might be able to include /usr/src/sys/dev/pci/pcivar.h, and get at the VPD by invoking `pci_get_vpd_readonly()`. I do not know how consistent vendors are in storing serial numbers in their device's VPD, so the results may be hit-or-miss.


----------



## j4ck (Jan 14, 2014)

Thanks. One of the input arguments of 
	
	



```
pci_get_vpd_readonly(device_t dev, const char *kw, const char **identptr)
```
 function is device_t pointer of the device. How can I access this pointer from user space? Could you please come up with some examples?


----------



## ralphbsz (Jan 17, 2014)

Doing this kind of stuff in user space is somewhere between impossible and impractically difficult.

You can't just access the PCI bus from user space. Imagine the kind of havoc that would cause with device drivers that are in the middle of using that same PCI bus (for example, in your case the network driver that is using the card). Synchronizing with accesses from the kernel is virtually impossible from user space.

Kernel data structures (like devices!) are not available in user space. For good reasons. Kernel code typically requires significant rework to compile in user space. And all the stuff such routines rely on then have to be recoded too. Furthermore, your user-space application will either need access to raw memory, or to CPU IO instructions; either of those can only be done as root, if at all.

What you propose amounts to writing a driver that runs in user space. This is occasionally done commercially, and I know examples (using AIX, Linux, and FreeBSD as the substrates). It takes tens of thousands of lines for a modern complex device, and multiple man-years. In the old days, when devices were really simple and had just a few IO ports, what you propose was still doable (and even then it was a hard way to go around doing it). Today, it's silly.

Suggestion: Do either of three things. One: find a way to get what you need from known system interfaces. For example the /sys file system on Linux, or the sysctl subsystem on *BSD tend to have lots of information which might do what you need. Two: Instead of doing this with a device that sits inside the machine (on a bus), use a device that sits behind a documented interface. For example, switch to a NIC that connects via SCSI or USB, then get libraries to send arbitrary USB or SCSI commands from user space. Those exist, and are often used to support really bizarre hardware for which no kernel drivers exist; for SCSI the capability of sending CDBs from user space is often called "passthrough". Three: Kernel programming is not actually very hard, it's just that it requires being very careful, and the debugging cycle is annoyingly long. Just take the existing driver for your device, understand, and add the capability you need (like an ioctl to read the serial number you need).


----------

