Zugriff auf Inhalt eines USB-Sticks mittels USB Device ID

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Hallo

Gibt es eine Möglichkeit den Pfad zu einem USB-Stick anhand dessen USB Device ID herauszufinden, um auf den Inhalt zugreifen zu können?

Gruß
Atalanttore
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Auf AMIGA OS?
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Wenn es unter Linux und Windows funktionieren würde, wäre ich vollkommen zufrieden.

Gruß
Atalanttore
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Für beides geht das nicht mit dem gleichen Code. Unter Linux sollte eigentlich alles unter /sys zu finden sein. Kann etwas hakelig werden, aber geht bestimmt. Oder du hörst auf die udev Ereignisse (habe ich gestern ein bisschen Code zu hier gepostet) und veknüpfts die Ereignisse durch ihre Daten. Erst kommt das USB device, dann das Blockdevice. Mit lsblk kann man (mit nettem json) erfahren, wo das blockdevice hin gemounted wurde.

Windows - kA. Auf der Ebene habe ich damit noch nicht gearbeitet.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Okay. Dann werde ich das mal probieren.

Gruß
Atalanttore
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Ich habe jetzt mehrere Sachen getestet, aber funktioniert hat nur folgendes Skript zur Erkennung von USB-Sticks, dass ich mit Informationen aus den Weiten des Internets zusammengebastelt habe.

Code: Alles auswählen

#!/usr/bin/python3

from usb.core import find
from usb.util import find_descriptor

DEVICE_CLASS_MASS_STORAGE = 0x0
INTERFACE_CLASS_MASS_STORAGE = 0x8


def get_mass_storage():
    for device in find(find_all=True, bDeviceClass=DEVICE_CLASS_MASS_STORAGE):
        for descriptor in device:
            if find_descriptor(descriptor, bInterfaceClass=INTERFACE_CLASS_MASS_STORAGE) is not None:
                return device


print(get_mass_storage())
Kann man mit den von dieser Funktion zurückgelieferten Daten schon den Einhängepunkt des USB-Sticks herausfinden?

Gruß
Atalanttore
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

In wenigen Tagen fange ich genau daran an zu arbeiten aus beruflichen Gründen. Wenn du Glück hast als Open Source. Wenn nicht, dann als ein paar Schnipsel.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__deets__: Dann hoffe ich mal das Beste (Open Source) und erwarte das Schlimmste (Closed Source mit NDA). :)

Was hast du eigentlich mit Blockdevice in "Erst kommt das USB device, dann das Blockdevice" gemeint?

Gruß
Atalanttore
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das erst das eine und dann das andere passiert. Wie moechtest du denn eine USB Festplatte benutzen, wenn du vorher nicht etabliert hast, dass es ueberhaupt irgendwas gab, das an den USB-Port angehangen wurde?
Benutzeravatar
Perlchamp
User
Beiträge: 172
Registriert: Samstag 15. April 2017, 17:58

warum benutzt du nicht USBDeview von Nirsoft ?
wer lesen kann ist klar im Vorteil ;-)
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Ein externes Windows-Programm, dass USB-Devices in einem Windows Fenster darstellt klingt jetzt nicht wie eine plattformunabhängige Lösung für Python.
Selbst wenn es ein CLI hat, kommt man sicher auch selbst an die Information.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

@Atalanttore: Nur damit ich das richtig verstehe: Du hast VID und PID des USB-Sticks und möchtest anhand dieser Angaben herausfinden, wo er ins System eingehängt ist, korrekt?
Die meisten USB-Sticks verwenden eine generische VID und eine generische PID die bei den meisten identisch ist. Was ja auch logisch ist. Bist du dir dessen bewusst? Ist der Stick so speziell, dass er eine eigene Geräteklasse hat? Falls nicht, kann es im Zweifelsfall dazu kommen, dass man den falschen von 2 angesteckten USB-Sticks auswählt, weil VID und PID identisch sind.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Er kann ja auch eine Seriennummer haben. Und das VID und PID identisch sind bei unterschiedlichen Herstellern ist ja auch eher ungewöhnlich. Und dann auch noch selbst mehrere gleich zu haben obendrauf....
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

So ungewöhnlich ist das nicht.
Gefühlt haben die eine Hälfte der USB-Stick "058f:6387" und die andere Hälfte "abcd:1234" als vid:pid.
Ungefühlt sind es alle, die ich hier habe.

Eigentlich ist das auch naheliegend, dass Hersteller das machen. Die Geräteklasse wird gebraucht, um den korrekten Treiber zu laden. Und wenn ein Treiber für einen generischen Massenspeicher reicht, geben die dem halt die vid:pid dafür mit.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das fuer mass-storage-devices (oder generell USB -Gearteklasssen) die VID:PID ausschliesslich eine Rolle spielen, waere mir neu.

Bei meinem gerade mal eingesteckten USB-Stick kommt mit lsusb folgendes raus:

Code: Alles auswählen

Bus 002 Device 078: ID 0781:5580 SanDisk Corp. SDCZ80 Flash Drive
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               3.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         9
  idVendor           0x0781 SanDisk Corp.
  idProduct          0x5580 SDCZ80 Flash Drive
  bcdDevice            0.10
  iManufacturer           1 SanDisk
  iProduct                2 Extreme
  iSerial                 3 XXXXX
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           44
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst              15
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst              15
Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength           22
  bNumDeviceCaps          2
  USB 2.0 Extension Device Capability:
    bLength                 7
    bDescriptorType        16
    bDevCapabilityType      2
    bmAttributes   0x00000002
      Link Power Management (LPM) Supported
  SuperSpeed USB Device Capability:
    bLength                10
    bDescriptorType        16
    bDevCapabilityType      3
    bmAttributes         0x00
    wSpeedsSupported   0x000e
      Device can operate at Full Speed (12Mbps)
      Device can operate at High Speed (480Mbps)
      Device can operate at SuperSpeed (5Gbps)
    bFunctionalitySupport   1
      Lowest fully-functional device speed is Full Speed (12Mbps)
    bU1DevExitLat           7 micro seconds
    bU2DevExitLat         101 micro seconds
Device Status:     0x0000
  (Bus Powered)
Es gibt zwar durchaus eine Liste der "ungewoehnlichen" USB mass storage devices, und die werden tatsaechlich nach VID:PID aufgeloest. Aber genauso wird mit "bInterfaceClass 8 Mass Storage" gearbeitet. Und ganz generell ist das ja auch die Idee hinter USB und seinen Deskriptoren. Den ganzen Aufstand braeuchte man ja nicht, wenn man nur zwei 16-Bit-Nummer zugrunde legt.

Und eine Serien-Nummer gibt's auch, also auch damit kann man einen Stick individuell identifizieren. Wird ja auch permanent gemacht. Wenn du nun natuerlich einen Stick aus einem chinesischen Ueberraschungsei benutzt, dann ist da dann irgendwann Hopfen und Malz verloren.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Natürlich sind das USB-Sticks aus chinesischen Überraschungseiern. Und im Zweifelsfall sind es ja die, die irgendwo in der Schreibtischschublade liegen.
Tatsächlich tut man sich unter Windows unglaublich schwer damit mit vid und pid voran zu kommen.
Das einfachste wäre, wenn man die "Volume Serial Number" dafür nehmen könnte. Da kann man sich per WMIC behelfen:

Code: Alles auswählen

import io
import subprocess
import sys

WMICPATH = r"C:\Windows\System32\wbem\wmic.exe"

def get_path_for_volumeserialnumber(number):
    if sys.platform == "win32":
        command = (WMICPATH, "logicaldisk", "get", "Caption,VolumeSerialNumber")
        proc = subprocess.Popen(command, stdout=subprocess.PIPE)
        for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
            try:
                caption, serial_number = line.strip().split()
                if serial_number == number:
                    return caption
            except ValueError:
                pass
    else:
        raise NotImplementedError("This works only on Windows")

if __name__ == "__main__":
    print(get_path_for_volumeserialnumber("C0D2B631"))
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Und hiermit sollte man unter Windows anhand der vid und der pid den Laufwerksbuchstaben ermitteln können.
Die Infos kommen aus der Registry.

Code: Alles auswählen

import sys
import winreg


def find_device_id(vendor_id, product_id):
    subkey = r"Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\CPC\Volume"
    volumeroot = winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey)
    volumenames = []
    try:
        for i in range(sys.maxsize):
            volumenames.append(winreg.EnumKey(volumeroot, i))
    except OSError:
        pass
    searchstring = bytearray("VID_{0}&PID_{1}".format(vendor_id, product_id),
                             "UTF-8")
    for volumename in volumenames:
        volumekey = winreg.OpenKey(volumeroot, volumename)
        data_value = winreg.QueryValueEx(volumekey, "Data")[0]
        cleared_value = data_value.replace(b"\0", b"")
        if searchstring in cleared_value:
            device_id = cleared_value[cleared_value.find(b"{"):
                                      cleared_value.find(b"}")]
            return device_id


def find_mountpoint_for_device(device_id):
    subkey = r"SYSTEM\MountedDevices"
    deviceroot = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey)
    try:
        for i in range(sys.maxsize):
            name, value, type_ = winreg.EnumValue(deviceroot, i)
            cleared_value = value.replace(b"\0", b"")
            if device_id in cleared_value and "DosDevices" in name:
                return name.split("\\")[-1]
    except OSError:
        pass


def get_path_for_usbid(vendor_id, product_id):
    if sys.platform == "win32":        
        device_id = find_device_id(vendor_id, product_id)
        if device_id:
            mountpoint = find_mountpoint_for_device(device_id)
            return mountpoint
    else:
        raise NotImplementedError("This works only on Windows")


if __name__ == "__main__":
    print(get_path_for_usbid("ABCD", "1234"))
Aber ich lege nicht meine Hand dafür ins Feuer, dass das immer tut.
Zumindest die Registry-Einträge unter HLM\SYSTEM\MountedDevices scheinen nicht so richtig konsistent zu sein. Da taucht bei mir der Eintrag für 2 Laufwerke auf, obwohl nur eins davon existiert. Es scheint aber, als würde der erste beim Durchlaufen auch der Neueste sein, deshalb müsste es passen.
Und ich tue mir nach wie vor schwer mit dieser Byte-Geschichte.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

__deets__ hat geschrieben: Montag 4. März 2019, 17:01 Das erst das eine und dann das andere passiert. Wie moechtest du denn eine USB Festplatte benutzen, wenn du vorher nicht etabliert hast, dass es ueberhaupt irgendwas gab, das an den USB-Port angehangen wurde?
Es müsste ein Signal ausgelöst werden, wenn ein USB-Speicher angesteckt wird.


@sparrow: Vielen Dank für den Code.


Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: Wäre schön, ist aber nicht vorgesehen. Unter Linux kann man sich per DBus über solche Ereignisse informieren lassen. :-)
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Atalanttore hat geschrieben: Dienstag 5. März 2019, 22:43
__deets__ hat geschrieben: Montag 4. März 2019, 17:01 Das erst das eine und dann das andere passiert. Wie moechtest du denn eine USB Festplatte benutzen, wenn du vorher nicht etabliert hast, dass es ueberhaupt irgendwas gab, das an den USB-Port angehangen wurde?
Es müsste ein Signal ausgelöst werden, wenn ein USB-Speicher angesteckt wird.
Eh. Was hat das denn mit deiner Frage und meiner Antwort darauf zu tun?

Wobei ich die Frage glaube ich auch falsch gelesen habe. Ein Blockdevice ist die Bezeichnung fuer Massenspeicher und ihrere Repraesentation in Linux. Mehr oder minder. Nicht, dass man das auch nachschauen koennte. https://unix.stackexchange.com/question ... ock-device

Und signale helfen doch nicht. Die haben keine Parameter. Woher weisst du denn, welches von den dutzenden /dev/sd*, /dev/nvme* oder was auch immer nun gerade das Geraet ist, das angesteckt wurde?
Antworten