I am writing a program which will print host, channel number, id number, lun of a SCSI device.
cat /proc/scsi/scsi
giving the information about it. But i want print it through c program. I'm getting vendor id, device type, revision level... but not lun , bus no etc.
Is there any ioctl command to get lun, bus, id numbers?
Did you try the ioctls for SCSI generic :
http://sg.danny.cz/sg/p/sg_v3_ho.html#ioctl ?
SCSI_IOCTL_GET_IDLUN, SG_GET_SCSI_ID should do the trick.
I did not use any SCSI HW in the last years though, and I hope the documentation is still valid for current kernels. I don't see any reason to have changed the ioctls though.
Related
GOAL:
I am trying to connect 4 RFID readers to a Pi and I need to differentiate each one's port.
WHAT I'VE DONE:
I entered lsusb into terminal with nothing but one reader plugged in. It returns :
Bus 001 Device 004: ID 0c27:232a RFIDeas, Inc
This is my reader.
So my Vendor ID should be 0c27 and my Product ID should be 232a
Now I need the serial # because all of my readers show the same Vendor and Product IDs.
My device is on port ttyACM0, so in terminal I search for the serial attribute as well as verify my product ID and vendor ID by putting:
udevadm info --name=ttyACM0 --attribute-walk | grep -i "serial" -e "product" -e "vendor"
This returns:
ATTRS{idProduct}=="232a"
ATTRS{idVendor}=="0c27"
ATTRS{product}=="USB Serial"
ATTRS{idProduct}=="9514"
ATTRS{idVendor}=="0424"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{product}=="DWC OTG Controller"
ATTRS{serial}=="3f980000.usb"
PROBLEM:
3 Product IDs and 3 Vendor IDs return. While only one serial # returns.
QUESTIONS:
Why does this return 3 Product IDs and 3 Vendor IDs when there is only one device connected?
Which ones am I supposed to use in my udev rules to make a persistent device name?
If I am leaving something out please let me know so I can update the question.
EDIT:
I have successfully created a udev rule using the first mentioned product ID and vendor ID:
SUBSYSTEM=="tty", ATTRS{idVendor}=="0c27", ATTRS{idProduct}=="232a", SYMLINK+="reader1"
This creates a working udev rule, BUT when I add the serial # ATTRS{serial}=="3f980000.usb" it stops working. I need a unique identifier.
While from your perspective you just plugged one device into your computer, the Linux kernel has a more complicated view of what is happening. The kernel keeps track of a hierarchy of devices, each with its own attributes, drivers, and child devices. The root of the hierarchy is usually some kind of root device representing your CPU, which is then connected (perhaps indirectly) to a USB controller device, which is connected to a "root hub", which is then connected to the physical USB device you plugged in, which in turn might have child devices for each function/interface that the USB device exposes.
You can run man udevadm to learn more about what the command does. It says:
-a, --attribute-walk
Print all sysfs properties of the specified device that can be used
in udev rules to match the specified device. It prints all devices
along the chain, up to the root of sysfs that can be used in udev
rules.
So there is this chain of devices, starting with ttyACM0 (a function of your USB device), and going up to the physical USB device, then the root hub, and then the USB controller, until it reaches the root of the heirarchy. The --attribute-walk option walks up that chain and prints out attributes of each of the devices along the way.
You are piping the output of that command into grep so you are not seeing the full output, and that it probably why you are confused. The full output of the command is actually very informative: it prints out a nice paragraph explaining what it does, and there are helpful sentences to make it clear when it switches from printing the attributes of one device to printing that of its parent. Here is some of the output I get when examining a USB device on my Raspberry Pi:
$ udevadm info --name=sda2 --attribute-walk
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda2':
KERNEL=="sda2"
SUBSYSTEM=="block"
[snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda':
KERNELS=="sda"
SUBSYSTEMS=="block"
[snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0':
KERNELS=="target0:0:0"
SUBSYSTEMS=="scsi"
[snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0':
KERNELS=="1-1.2.1:1.0"
SUBSYSTEMS=="usb"
[snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1':
KERNELS=="1-1.2.1"
SUBSYSTEMS=="usb"
[snip]
[... and so on, up to the root device]
Unfortunately, from the output of your udevadm command, it looks like your RFID adapter does not have a USB serial number, so distinguishing it from other devices of the same model might by tricky. To confirm it doesn't have a serial number, I recommend that you run lsusb -v -d 0c27:232a | grep iSerial. If the number after iSerial is 0, it means there is no serial number.
I recommend looking at the symbolic links that Linux creates for you in /dev/serial/by-id; maybe those symbolic links will have enough detail in their names so that you don't need to create a new udev rule. (Hint: run ls -lR /dev/serial/by-id.)
If you still need more help finding or creating stable symbolic links, I think you should plug in all four RFID readers and then post the full output from each of these commands:
ls -lR /dev/serial/by-id
ls /dev/ttyACM*
udevadm info --name=ttyACM0 --attribute-walk
I was able to create a udev rule by putting in the following:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1d6b", ATTRS{idProduct}=="0002", ATTRS{serial}=="3f980000.usb", SYMLINK+="reader1"
The reason for multiple Product and Vendor IDs is explained by David Grayson's answer quoted below. This is what lead me to the solution.
While from your perspective you just plugged one device into your computer, the Linux kernel has a more complicated view of what is happening. The kernel keeps track of a hierarchy of devices, each with its own attributes, drivers, and child devices. The root of the hierarchy is usually some kind of root device representing your CPU, which is then connected (perhaps indirectly) to a USB controller device, which is connected to a "root hub", which is then connected to the physical USB device you plugged in, which in turn might have child devices for each function/interface that the USB device exposes.
You can run man udevadm to learn more about what the command does. It says:
-a, --attribute-walk
Print all sysfs properties of the specified device that can be used
in udev rules to match the specified device. It prints all devices
along the chain, up to the root of sysfs that can be used in udev
rules.
So there is this chain of devices, starting with ttyACM0 (a function of your USB device), and going up to the physical USB device, then the root hub, and then the USB controller, until it reaches the root of the heirarchy. The --attribute-walk option walks up that chain and prints out attributes of each of the devices along the way.
You are piping the output of that command into grep so you are not seeing the full output, and that it probably why you are confused. The full output of the command is actually very informative: it prints out a nice paragraph explaining what it does, and there are helpful sentences to make it clear when it switches from printing the attributes of one device to printing that of its parent. Here is some of the output I get when examining a USB device on my Raspberry Pi:
$ udevadm info --name=sda2 --attribute-walk
Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device.
looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda2': KERNEL=="sda2" SUBSYSTEM=="block" [snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda': KERNELS=="sda" SUBSYSTEMS=="block" [snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0': KERNELS=="target0:0:0" SUBSYSTEMS=="scsi" [snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0': KERNELS=="1-1.2.1:1.0" SUBSYSTEMS=="usb" [snip]
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1': KERNELS=="1-1.2.1" SUBSYSTEMS=="usb" [snip]
[... and so on, up to the root device]"
What goes behind the hood when i add a new NIC card to my Ubuntu machine.?
Which program/module is responsible for mapping the HardWare address of the device to a name(eth0/eth1). Where are this mappings(HWaddress1-eth0, HWaddress2-eth1) actually stored.?
As far as I know the kernel itself will name the nics depending on the order they are connected to the bus. This behavior is very similar to SCSI/SATA naming.
Take a look at the output of
lspci
You should find the corresponding network card there. The first column e.g. 0000:00:03.0 contains the following information:
0000 : PCI domain (each domain can contain up to 256 PCI buses)
00 : the bus number the device is attached to
03 : the device number
.0 : PCI device function
(source: http://prefetch.net/articles/linuxpci.html)
under /sys/bus/pci(_express)/devices/ you will find links that match to the lspci output. When you enter the folder of your network card, there are lots of files and folders.
You can do a find and grep
cd /sys/bus/.../devices/0000:00:03.0/
someuser#somemachine:/sys/bus/pci/devices/0000:00:03.0$ find -type f -exec grep 'ethX' /dev/null {} \; 2>/dev/null
where ethX is your device name to get an output like
./virtio0/net/ethX/uevent:INTERFACE=eth0
(in my case a virtual machine with a virtio device)
Since this information is derived from the running kernel I bet you will also find the hardware-address there.
Happy grepping!
I'm developing a driver for an FPGA-board connected to my machine via an PCIe expansion slot, and everything works great if the board is powered on prior to the PC. However, if I book up my computer first and then the FPGA board, I get the rather unusual behavior of the device being recognized and loading my module (I see the "init" function called in my syslog), however the "probe" function is never called.
I think this is due to an invalid BAR0. Output from dmesg when I power on the board:
[ 71.287587] pci 0000:3b:00.0: [0ae5:0001] type 00 class 0x000000
[ 71.287613] pci 0000:3b:00.0: reg 0x10: [mem 0x00000000-0x0000ffff]
[ 71.287821] pci 0000:3b:00.0: System wakeup disabled by ACPI
[ 71.328537] my_driver:
[ 71.328537] ****************************************************************
[ 71.328542] my_driver: init debug=2
That first reg should be something like 0xb4000000-0xb400ffff but instead it's coming up as 0. (Like I said, it works perfectly if it's powered on before the computer).
Is there an additional step required to get it to allocate this block? Or somehow to indicate to the kernel that it needs to do this?
The solution wound up being a manual call to pci_assign_resource ( http://lxr.free-electrons.com/source/drivers/pci/setup-res.c#L283 ).
Calling this right before pci_enable_device caused the OS, rather than the BIOS, to allocate the required BAR's and now it all works!
I do still have to manually trigger a PCI bus rescan ( echo 1 > /sys/bus/pci/rescan ).
Your PCI device must be powered up prior to the BIOS PCI enumeration phase.
On enumeration phase, the BIOS tries to read the ID of the PCI devices that might be connected.
If it reads invalid ID (0xfffff) it skips that PCI device.
I don't have a reference, but AFAIK, you have about a second before you must populate the configuration space of the PCI.
Are you sure you register the PCI driver and don't return non-zero from mod_init? Please try to manually bind the device to your driver:
echo -n "0000:3b:00.0" > /sys/bus/pci/drivers/my_driver/bind
Unallocated BAR should not be an issue when loading the driver.
As for the BAR being 0 and HotPlug: find out what is your platform and if and how HotPlug is supported. You need to have the right HotPlug driver in the kernel for this sort of thing to work. BARs are allocated by the kernel (or initially firmware/BIOS) so you can't set them to anything meaningful from the FPGA side - there you can only set the size. Kernel has to do the rescanning and reassignment after device appears. I vaguely recall that there should be some reservation going on during boot, otherwise kernel will not have to space to give to your devices' BAR and it will not reassign the windows on bridges below your device as they can be actively used by other devs. Other option is to just do the BAR programming yourself from the driver. It ain't that hard but you would probably don't want to ship this kind of hacks to customers. Also, even though your device does seem to come up fine, make sure you don't have HP disabled in FW/BIOS.
ls -l /dev
command lists the device files, and the associated information like major number, minor number.
cat proc/devices
command helps me to find the device name associated with a major number.
So for a node, I have found the major number, device name.
I understood how to auto create a device file, by populating the class information under /sys/class => By installing the device driver module, i can find the device file created.
I cant trace back from device file to the corresponding module.
In essence,how to find the Device driver/module associated with the device file, with these information?
I have several USB mass storage flash drives connected to a Ubuntu Linux computer (Ubuntu 10.04.1, kernel 2.6.32-25-386), and I need to tell them apart programatically (from bash if possible, but I'm not afraid of compiling either) - I need to find which block device corresponds to which physical device (e.g. /dev/sdb1 -> device in USB port 1; in my case, one device ~ one volume).
In other words, I know that I have three hardware devices plugged into USB ports; each of them shows up in the system as a USB mass storage device (as seen with lsusb), is created as a block device (/dev/sdb1) and automounted by UUID (/media/1234-5678).
USB device block device mountpoint
USB device in port 2.2 <-> /dev/sdb1 <-> /media/1234-5678
I'm not trying to find the relationship between block device and mountpoint; I'm trying to find the relationship between block device and USB device, is there a way?
Why? There will be some writes on the disks, with unpredictable time of completion. I need to give the operator some indication like "you can now remove the disk in port 2 (which is second from the left)". I have found which physical port corresponds to which port number on that specific machine, and finding block devices from mountpoints is simple; now I'm stuck mapping the logical USB ports to block devices.
I can see the disks with lsusb :
Bus 001 Device 058: ID 067b:2517 Prolific Technology, Inc. Mass Storage Device
Bus 001 Device 060: ID 067b:2517 Prolific Technology, Inc. Mass Storage Device
Bus 001 Device 061: ID 067b:2517 Prolific Technology, Inc. Mass Storage Device
and I can see them mounted (by their UUID):
/dev/sdb1 on /media/BC88-15C4 type vfat
/dev/sdc1 on /media/AE54-65AA type vfat
/dev/sdd1 on /media/58D2-FED1 type vfat
Now, all the drives are the same model from the same manufacturer, so I can't distinguish them by that, and I can't guarantee they'll be plugged in a particular order.
I have found /sys/bus/usb/devices (a list of USB devices), but it seems to be the same data that I get from lsusb - I don't see a mapping to disks there.
There's also /sys/block/sdb and /sys/block/sdb/sdb1 (the block device and its first partition; similarly for sdc and sdd), but again, I see no mapping to devices.
I'm not sure in which kernel version this was implemented, but the /sys/block/* entries are symlinks to the devices.
In other words, /sys/block/sdb symlinks to a different directory, and its name contains the USB device ID.
$ file /sys/block/sdb
/sys/block/sdb: symbolic link to `../devices/pci0000:00/0000:00:02.1/usb1/1-1/1-1.1/1-1.1:1.0/host31/target31:0:0/31:0:0:0/block/sdb'
USB version and port here---^^^^^
The 1-1.1 is the interesting part, denoting usb1-port 1.device 1. When plugged into a hub, another level is added: 1-2.3.1, denoting usb1-port 2.port 3.device 1.
Pseudocode:
get partition name # e.g. /dev/sdb1
get disk name # that would be /dev/sdb
get your basename # sdb
see where /sys/block/$your_basename points to # e.g. ../devices/blah/blah/1-2.1/blah
get the longest substring matching "\d-\d+(.\d+)*" # e.g. 1-2.1
that is the device id you want
/sys/bus/usb/devices/$device_id/ has all kinds of information about it
the ID corresponds to hardware USB ports
Working example script in bash.
I use the path:
/sys/bus/usb/drivers/usb-storage/4-1:1.0/host4/target4:0:0/4:0:0:0/block/sda
so you can see usb bus 4, port 1 is connected with a usb storage /dev/sda
Can't you use disk labels?
http://ubuntuforums.org/showthread.php?t=322973
Here is how I do it.
lsusb -v shows all the devices disks get an iserial number take note of them
ls -l /dev/disk | grep [iserial]
Everything in /dev/disk is a symlink so follow the symlink to see the device.