bash, search for usb storage devices. output location - linux

I am looking for a way to list any usb connected devices or removable storage media.
I will be using this list for a gtk boot media writer, so a user can easily write an iso to a usb.
This creates a perfect list of ALL partitions:
ls /dev | grep "[sh]d[a-z][1-9]"
How can I get a similar looking list that is only removable media?

On my system (Ubuntu 12.04), I can get a list of USB devices and partitions with
ls /dev/disk/by-path/*usb*
giving
/dev/disk/by-path/pci-0000:00:02.1-usb-0:1.1:1.0-scsi-0:0:0:0
/dev/disk/by-path/pci-0000:00:02.1-usb-0:1.1:1.0-scsi-0:0:0:0-part1
or partitions alone
ls /dev/disk/by-path/*usb*part*
These are symbolic links, pointing to the real device files, /dev/sdd and /dev/sdd1 for example.
I have tested this with a USB stick and an external USB hard disk only. I cannot say, whether or how this works with eSATA or Firewire disks.

Based on the answer of Olaf Dietsche, I end up with the following:
devs=`ls -al /dev/disk/by-path/*usb*part* 2>/dev/null | awk '{print($11)}'`; for dev in $devs; do dev=${dev##*\/}; echo -n "$dev ("; echo -n `mount | grep \`echo -E ${dev}\` | awk '{print($3)}'`; echo ")"; done
For me the above code is showing the usb devices and where they are mounted (between parentheses). It worked on Ubuntu 13.04 and 12.04.2, but I do not know if it will work on any other system.

Maybe you can use the output of lsusb command :
lsusb
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0db0:3870 Micro Star International
Bus 002 Device 003: ID 0000:0000
Bus 002 Device 004: ID 14cd:6116 Super Top M6116 SATA Bridge

To get the mounted path of usb storage use
mount|grep /media|awk '{print $3}'
explanation to command
mount will print all the mounted drives and grep will display only drives mounted in /media, (considering /media is default mount point ) this output is piped to awk which will print the mounted path of usb drive

bootiso BASH utility just do that when called with -l option. Here is the output of a slightly modified bash snippet:
/dev/sdd /dev/sde
Relevant snippet:
printUSBDevices() {
typeset -a usbDevices
typeset -a devices
getDeviceType() {
typeset deviceName=/sys/block/${1#/dev/}
typeset deviceType=$(udevadm info --query=property --path="$deviceName" | grep -Po 'ID_BUS=\K\w+')
echo "$deviceType"
}
mapfile -t devices < <(lsblk -o NAME,TYPE | grep --color=never -oP '^\K\w+(?=\s+disk$)')
for device in "${devices[#]}" ; do
if [ "$(getDeviceType "/dev/$device")" == "usb" ]; then
usbDevices+=("/dev/$device")
fi
done
echo "${usbDevices[#]}"
}
printUSBDevices

Related

Obtaining information about /dev/usb/lp* devices

I have a problem obtaining information about /dev/usb/lp* devices.
The lsusb command gives me USB bus and device IDs, and a name of the device but I can't figure out how to get it to tell me the name of the corresponding /dev/usb/lp* device.
I don't have CUPS available.
You can use libudev to get the equivalent of the following command:
$ udevadm info -a /dev/usb/lp*
In my PC it prints something like:
looking at device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.1/usbmisc/lp2':
KERNEL=="lp2"
SUBSYSTEM=="usbmisc"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.1':
KERNELS=="1-1.3:1.1"
SUBSYSTEMS=="usb"
DRIVERS=="usblp"
...
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3':
KERNELS=="1-1.3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
...
ATTRS{idProduct}=="341b"
ATTRS{idVendor}=="04e8"
...
And there they are! The wanted idProduct and the idVendor
You can also get the information by navigating the /sys directory manually:
$ ls -l /dev/usb/lp2
crw-rw---- 1 root lp 180, 2 Sep 27 11:46 /dev/usb/lp2
$ readlink -f /sys/dev/char/180:2
/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.1/usbmisc/lp2
$ cat /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/{idVendor,idProduct}
04e8
341b

Detect if a block device is a local disk or a removable usb disk

There's any way to detect if a block device, like /dev/sda or /dev/sdc, is related to a local disk (scsi or sata I mean) or to a removable USB disk?
I'm writing a shell script that have to detect ONLY local disks block devices, excluding any removable disks.
Thanks!
You can use udev, the Linux device manager.
Querying for each block device will show several informations about it, including the bus, which you can use in order to discern if the device is a removable USB one.
This is the script:
for device in /sys/block/sd*; do
device_info="$(udevadm info --query=property --path=$device)"
device_name=$(echo "$device_info" | perl -ne 'print "$1" if /^DEVNAME=(.*)/')
device_bus=$(echo "$device_info" | perl -ne 'print "$1" if /^ID_BUS=(.*)/')
echo "Device $device_name bus: $device_bus"
done
and this is a sample result:
Device /dev/sda bus: ata
Device /dev/sdb bus: ata
Device /dev/sdc bus: usb
Use lshw:
lshw -class disk -class storage
and look for the bus info string.

RS232 console communication - set baudrate to 1 MBaud

Within a bash script, I use the following:
$ stty -F /dev/ttyUSB0 921600 raw
$ echo -n "some test data" >/dev/ttyUSB0
and it works as expected.
Using a PL2303 USB to RS232 adapter:
$ lsusb
...
Bus 006 Device 010: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 006 Device 011: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Now I tried to do the same with 1 MBd, but got an error:
$ stty -F /dev/ttyUSB0 1000000 raw
stty: /dev/ttyUSB0: unable to perform all requested operations
Also the same message when I try with 500 kBd. Trying 250 kBd the error message is different:
$ stty -F /dev/ttyUSB0 250000 raw
stty: invalid argument `250000'
Try `stty --help' for more information.
As seen here, it's a problem in the PL2303 linux driver.
I'm working on Kubuntu 12.04, 32 Bit. Unfortunally, I don't know how to fix that driver on my system (getting driver source, patch em, compile, install … hmm, maybe I learn a bit and give it a try - advice is welcome).
But maybe there is an updated driver avaliable which is easy to install?
Or does someone know an alternate USB to RS232 adapter which works at 1 MBd (hardware flowcontrol via rts/cts is needed, which works pretty well with the PL2303)?
After the realization that »Prolific and FTDI are competitors«, I bought Ftdi US232R-10 which is a FT232R based device and specified for 1 MBd transfer rate.
With this adapter I'd successfully tested communication at 1 MBd by transfering some GiB data without any error (including usage of Rts/Cts hardware flow control).
Configuring this device using stty like:
$ stty -F /dev/ttyUSB0 1000000 raw
works successfully.

Disconnect and reconnect ttyUSB0 programmatically in Linux

Trying to solve this problem (ttyUSB0 that works properly than stop working after about 1hr)I'm thinking on if disconnecting and reconnecting the usb device could be a good fix.
So, it is possibile to cut down power to the USB device and repower it programmatically (bash)?
# lsusb -t
1-1:1.0: No such file or directory
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=musb-hdrc/1p, 480M
|__ Port 1: Dev 2, If 0, Class=vend., Driver=, 12M
|__ Port 1: Dev 2, If 1, Class=vend., Driver=cp210x, 12M
On am335x, kernel 3.2.0, ubuntu core armhf.
[ 1.784332] usb 1-1: cp210x converter now attached to ttyUSB0
At the moment I need a complete power cycle to have ttyUSB0 back.
This is the solution:
Find the identity of your usb device.
# tree /sys/bus/usb/drivers/cp210x/
/sys/bus/usb/drivers/cp210x/
|-- 1-1:1.1 -> ../../../../devices/platform/omap/musb-ti81xx/musb-hdrc.1/usb1/1-1/1-1:1.1
|-- bind
|-- module -> ../../../../module/cp210x
|-- remove_id
|-- uevent
-- unbind
So 1-1:1.1 is the identifier of my ttyUSB0(it can be discovered also via dmesg).
Then, disconnect the device (as root):
# echo -n "1-1:1.1" > /sys/bus/usb/drivers/cp210x/unbind
reconnect it
# echo -n "1-1:1.1" > /sys/bus/usb/drivers/cp210x/bind
At this point I had the same device but with a different name, it was now ttyUSB1 instead of ttyUSB0.
- To avoid this I added a new rule in /etc/udev/rules.d/ by creating a new file named 99-usb-serial.rules with this line:
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea70", ATTRS{serial}=="002DCFAF", SYMLINK+="sameName", MODE:="0666"
where idVendor, idProduct and serial must be the values of your device. This rule will create a new device called sameName linked to the ttyUSB* device normally generated from the OS.
As #Robert Harvey Said,
You first need to find our driver that will help you 'unplug and plug' the usb. Type: ls /sys/bus/usb/drivers which should print something like this: btusb ftdi_sio hub usb usbfs usbhid usbserial_generic uvcvideo. These, are all the drivers for each usb device. Now, lets say mine is ftdi_sio, which is a device i use to program my arduino (atmega328p chip). I am not sure how Your/other usb devices name themselves there. Like, i dont know which of these is my mouse.
Now, you can see the driver's commands using:
ls /sys/bus/usb/drivers/ftdi_sio/, which will print something like: 1-4:1.0 bind module uevent unbind, Where 1-4:1.0 is the device's characteristic code, and the bind and unbind command, which are the 'plug' and 'unplug' command respectively.
Now, if i want to unplug programatically the ftdi usb port, i will type:
echo -n "1-4:1.0" > /sys/bus/usb/drivers/ftdi_sio/unbind
and, to plug it again:
echo -n "1-4:1.0" > /sys/bus/usb/drivers/ftdi_sio/bind
Now, we can combine all the commands together, with a ';':
echo -n "1-4:1.0" > /sys/bus/usb/drivers/ftdi_sio/unbind ; echo -n "1-4:1.0" > /sys/bus/usb/drivers/ftdi_sio/bind

BASH find which port a USB drive is attached to by the PCI ID

Basically I need to verify that a USB Drive is connected to a certain USB Port. I have the following:
USB Drives are labeled virtually:
White, Green, Red
I have 3 USB Ports that are also labeled physically:
White, Green, Red
Using BLKID I can receive information from the drives such as
BLKID Example
/dec/sdb1: SEC_TYPE="msdos" LABEL="WHTIE" UUID="78FE-870D" TYPE="vfat"
Therefore I know a lot about the drive itself by only knowing the label. Now I using LSPCI I can get the information about the USB port as I know the ID's of each bridge. For example:
LSPCI Example
0a.00.0 USB Controller: some info 4d88
So that last part 4d88 is the PCI ID.
So I know the PCI ID's of each port and need to match them up to the USB Drive itself such as:
4d88 = WHITE
4dC0 = GREEN
4d84 = RED
I don't know how to match / check that relationship. Any help will be appreciated.
ANSWER: Thanks for all the help.
#!/bin/bash
#variables
error="ERROR : Incorrect Command use 'usb_pci.sh'"
pci="USB PCI Check Successful"
errorstatus_white_pci="ERROR : USB PCI FAILED : WHITE Drive"
errorstatus_green_pci="ERROR : USB PCI FAILED : GREEN Drive"
errorstatus_red_pci="ERROR : USB PCI FAILED : RED Drive"
pci_check_white=4dc9
pci_check_green=4d81
pci_check_red=4dc5
#Takes USB label and gets /sys/block/sd?
echo "checking path for USB Label"
path_white=$(blkid | grep WHITE | cut -d : -f 1 | sed 's|[0-9]*$||; s|^/dev/|/sys/block/|')
echo "white: "$path_white
path_green=$(blkid | grep GREEN | cut -d : -f 1 | sed 's|[0-9]*$||; s|^/dev/|/sys/block/|')
echo "green: "$path_green
path_red=$(blkid | grep RED | cut -d : -f 1 | sed 's|[0-9]*$||; s|^/dev/|/sys/block/|')
echo "red: "$path_red
#Takes /sys/block/sd? and gets PCI Path xx:xx.x
echo "checking path to PCI path"
pci_path_white=$(ls -l ${path_white} | xargs | cut -d / -f 8 | cut -b 6-13)
echo "white: "$pci_path_white
pci_path_green=$(ls -l ${path_green} | xargs | cut -d / -f 8 | cut -b 6-13)
echo "green: "$pci_path_green
pci_path_red=$(ls -l ${path_red} | xargs | cut -d / -f 8 | cut -b 6-13)
echo "red: "$pci_path_red
#Takes xx:xx.x and gets the PCI Device ID xxxx
echo "checking PCI path to PCI Device ID"
pci_device_id_white=$(lspci -s ${pci_path_white} | tail -c -5)
echo "white: "$pci_device_id_white
pci_device_id_green=$(lspci -s ${pci_path_green} | tail -c -5)
echo "green: "$pci_device_id_green
pci_device_id_red=$(lspci -s ${pci_path_red} | tail -c -5)
echo "red: "$pci_device_id_red
#check if pci_device_id_xxxx = pci_check_xxxx
echo "checking PCI Device ID equals what it should"
if [ $pci_device_id_white = $pci_check_white ] ; then
echo "WHITE USB PCI Check Successful"
else
echo $errorstatus_white_pci
exit 1
fi
if [ $pci_device_id_green = $pci_check_green ] ; then
echo "GREEN USB PCI Check Successful"
else
echo $errorstatus_green_pci
exit 1
fi
if [ $pci_device_id_red = $pci_check_red ] ; then
echo "RED USB PCI Check Successful"
else
echo $errorstatus_red_pci
exit 1
fi
echo $pci
exit 0
Edit:
As requested dumps of lspci, lsusb, blkid.
lspci
00:00.0 Host bridge: Intel Corporation Unknown device 0104 (rev 09)
00:02.0 VGA compatible controller: Intel Corporation Unknown device 0126 (rev 09)
00:16.0 Communication controller: Intel Corporation Unknown device 1c3a (rev 04)
00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (rev 04)
00:1a.0 USB Controller: Intel Corporation Unknown device 1c2d (rev 04)
00:1b.0 Audio device: Intel Corporation Unknown device 1c20 (rev 04)
00:1c.0 PCI bridge: Intel Corporation Unknown device 1c10 (rev b4)
00:1c.2 PCI bridge: Intel Corporation Unknown device 1c14 (rev b4)
00:1c.3 PCI bridge: Intel Corporation Unknown device 1c16 (rev b4)
00:1c.5 PCI bridge: Intel Corporation Unknown device 1c1a (rev b4)
00:1d.0 USB Controller: Intel Corporation Unknown device 1c26 (rev 04)
00:1f.0 ISA bridge: Intel Corporation Unknown device 1c4f (rev 04)
00:1f.2 RAID bus controller: Intel Corporation Mobile 82801 SATA RAID Controller (rev 04)
00:1f.3 SMBus: Intel Corporation Unknown device 1c22 (rev 04)
08:00.0 PCI bridge: Integrated Device Technology, Inc. PES4T4 PCI Express Switch (rev 0e)
09:02.0 PCI bridge: Integrated Device Technology, Inc. PES4T4 PCI Express Switch (rev 0e)
09:03.0 PCI bridge: Integrated Device Technology, Inc. PES4T4 PCI Express Switch (rev 0e)
09:04.0 PCI bridge: Integrated Device Technology, Inc. PES4T4 PCI Express Switch (rev 0e)
0a:00.0 USB Controller: Unknown device 4d88
0a:00.1 USB Controller: Unknown device 4dc9
0a:00.2 System peripheral: Unknown device 4dca
0a:00.3 Communication controller: Unknown device 4d8b
0b:00.0 USB Controller: Unknown device 4dc0
0b:00.1 USB Controller: Unknown device 4d81
0b:00.2 System peripheral: Unknown device 4d8e
0b:00.3 Serial controller: Unknown device 4dcf
0c:00.0 USB Controller: Unknown device 4d84
0c:00.1 USB Controller: Unknown device 4dc5
0c:00.2 System peripheral: Unknown device 4dc6
0c:00.3 Communication controller: Unknown device 4d87
0d:00.0 SD Host controller: O2 Micro, Inc. Unknown device 8221 (rev 05)
0d:00.1 Mass storage controller: O2 Micro, Inc. Unknown device 8231 (rev 03)
lsusb
Bus 004 Device 001: ID 0000:0000
Bus 006 Device 001: ID 0000:0000
Bus 005 Device 001: ID 0000:0000
Bus 001 Device 002: ID 8087:0024
Bus 001 Device 001: ID 0000:0000
Bus 007 Device 001: ID 0000:0000
Bus 008 Device 001: ID 0000:0000
Bus 003 Device 003: ID 0718:063d Imation Corp.
Bus 003 Device 001: ID 0000:0000
Bus 002 Device 002: ID 8087:0024
Bus 002 Device 004: ID 0a5c:5800 Broadcom Corp. BCM5880 Secure Applications Processor
Bus 002 Device 001: ID 0000:0000
Bus 002 Device 003: ID 413c:3012 Dell Computer Corp. Optical Wheel Mouse
blkid
/dev/mapper/VolGroup00-LogVol01: TYPE="swap" UUID="6b361baf-08ae-4f2c-933b-5028c15b6fb5"
/dev/mapper/VolGroup00-LogVol00: UUID="d15840ac-0073-483d-b630-7d2a497eaac9" TYPE="ext3"
/dev/sda1: LABEL="/boot" UUID="39331b93-a08d-45b5-b1ea-fcc6586be7bd" TYPE="ext3"
/dev/VolGroup00/LogVol00: UUID="d15840ac-0073-483d-b630-7d2a497eaac9" TYPE="ext3"
/dev/VolGroup00/LogVol01: TYPE="swap" UUID="6b361baf-08ae-4f2c-933b-5028c15b6fb5"
/dev/sdb1: SEC_TYPE="msdos" LABEL="WHITE" UUID="78FE-870D" TYPE="vfat"
/dev/sdc1: SEC_TYPE="msdos" LABEL="GREEN" UUID="61FE-B32E" TYPE="vfat"
/dev/sdd1: SEC_TYPE="msdos" LABEL="RED" UUID="E5DB-4A1A" TYPE="vfat"
This is how I would do it on my system:
Step 1: Find the device node:
# blkid | grep MyDisk
/dev/sdj1: LABEL="MyDisk-0" UUID="4876-5945" TYPE="vfat"
The device node is /dev/sdj1.
Step 2: /sys is your friend:
# ll /sys/block/sdj
lrwxrwxrwx 1 root root 0 Feb 3 00:40 /sys/block/sdj -> ../devices/pci0000:00/0000:00:1a.7/usb1/1-2/1-2:1.0/host15/target15:0:0/15:0:0:0/block/sdj/
The symbolic link target above contains a lot of useful information, including the path from your flash drive back to the PCI bridge via the SCSI and USB subsystems.
Step 3: From the link target above isolate the PCI bus ID (00:1a.7 in this case) and check with lspci:
# lspci | grep 00:1a.7
00:1a.7 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2
If in doubt, inspect the lspci output visually...
EDIT:
Here is an extremely crude and extremely fragile way to automate the process above:
blkid |
grep Label |
cut -d : -f 1 |
sed 's|[0-9]*$||; s|^/dev/|/sys/block/|' |
xargs readlink |
cut -d / -f 4 |
xargs -n 1 lspci -s
NOTE: This works on my system, but it is by no means safe (or recommended):
It will break if a kernel update changes the layout of the /sys filesystem.
It can break if you have a different device layout, although you should be able to adjust for that.

Resources