Hogyan ébreszthetjük fel, indíthatjuk újra kikapcsolt, szoftveresen leválasztott (kiadott) külső tárolóeszközeinket az USB gyökérhub-ok újraindításával

botond küldte be 2021. 04. 06., k – 22:50 időpontban

Tartalom

 

Bevezető

Ha külső USB-s meghajtókat, tárolóeszközöket használunk, Linux rendszerünk grafikus asztalkörnyezetében ezeket néhány kattintással biztonságosan leválaszthatjuk, lekapcsolhatjuk. Az így kiadott eszközökhöz utána már nem férünk hozzá, mivel a hozzájuk tartozó blokk eszköznevek megszűnnek és a hardverek is áramtalanításra kerülnek. Alapesetben csak a hardverek fizikai újracsatlakoztatásával tudjuk azokat újra használatba venni, ami emberi beavatkozást igényel.

Felmerülhet az igény arra, hogy az így szoftveresen leválasztott, kikapcsolt tárolóeszközünkhöz mégis hozzá szeretnénk férni anélkül, hogy fizikailag ki kelljen húzni, majd újracsatlakoztatni azokat. Például ha van egy egy külső USB-s merevlemezünk, amire napi adatmentéseket teszünk, de nem szeretnénk, hogy a mentés előtt és után bekapcsolva legyen a meghajtó; mindezt automatizáltan, külön beavatkozás nélkül szeretnénk megoldani, hogy a mentés előtt bekapcsolja az eszközt és felcsatolja, a mentés végeztével pedig lecsatolja és kikapcsolja azt (tehát ne csak altassa).

De ha bármi egyéb okból hozzá szeretnénk tudni férni a logikailag leválasztott és áramtalanított USB-s tárolóeszközünkhöz, akkor ebben a leírásban megnézzük, hogyan lehet újból elindítani és hozzáférhetővé tenni külső HDD meghajtónkat, pendrive-unkat vagy kártyaolvasónkat anélkül, hogy fizikailag újra kellene csatlakoztatnunk azt.

 

 

USB szabványok és verziók

Mielőtt nekiállnánk bárminek, először érintőlegesen ejtenünk kell néhány szót az USB szabványokról és verziókról; éppen csak annyit, hogy a leírás további részeit könnyebben megérthessük. A mai feladathoz az USB szabványok, azaz a különféle Host Controller Interface (HCI)-k felől kell megközelítenünk a dolgokat. A Host Controller, magyarul a gazdavezérlő vagy állomásvezérlő gondoskodik a perifériák és a számítógép közötti kommunikációról, amihez többféle interfész is létezik. Tekintsük át ezeket röviden a teljesség igénye nélkül:

OHCI (Open Host Controller Interface)

Az Open Host Controller Interface (OHCI) egy nyílt szabvány, amely az Universal Host Controller Interface (UHCI) mellett alkotja az USB 1.x hardver vezérlő interfész szabványát.

  • Támogatott USB verziók: USB 1.0, USB 1.1
  • Maximális adatátviteli sebességek:
    • USB 1.0 (Low Speed mód): 1,5 Mbps (0,1875 Mb/s)
    • USB 1.1 (Full Speed mód): 12 Mbps (1,5 Mb/s)
  • Vezérlő(k): ohci-pci, ohci_hcd

UHCI (Universal Host Controller Interface)

Az Universal Host Controller Interface (UHCI) az Intel által létrehozott interfész az USB 1.x (alacsony és teljes sebesség) számára. Ennek használatához a hardvergyártóknak licencre van szüksége az Inteltől.

  • Támogatott USB verziók: USB 1.0, USB 1.1
  • Maximális adatátviteli sebességek:
    • USB 1.0 (Low Speed mód): 1,5 Mbps (0,1875 Mb/s)
    • USB 1.1 (Full Speed mód): 12 Mbps (1,5 Mb/s)
  • Vezérlő(k): uhci-pci

EHCI (Enhanced Host Controller Interface)

Az Enhanced Host Controller Interface (EHCI) az USB 2.0-ra alkalmazható nagy sebességű vezérlő szabvány, ami szintén az Intel tulajdona.

  • Támogatott USB verzió: USB 2.0
  • Maximális adatátviteli sebességek:
    • USB 1.0 (Low Speed mód): 1,5 Mbps (0,1875 Mb/s)
    • USB 1.1 (Full Speed mód): 12 Mbps (1,5 Mb/s)
    • USB 2.0 (High-speed mód): 480 Mbps (60 Mb/s)
  • Vezérlő(k): ehci-pci

xHCI (Extensible Host Controller Interface)

Az Extensible Host Controller Interface (xHCI) a jelenlegi legújabb gazdavezérlő szabvány, amely elődjeihez képest javítja a sebességet, az energiahatékonyságot és a virtualizációt. Célja, hogy leváltsa a korábbi (OHCI/UHCI/EHCI) gazdavezérlő interfészeket. Támogatja az összes korábbi USB-eszköz sebességét, valamint ez is az Intel szabványa.

  • Támogatott USB verziók: USB 1.1, USB 2.0, USB 3.0, USB 3.1
  • Maximális adatátviteli sebességek:
    • USB 1.1 (Full Speed mód): 12 Mbps (1,5 Mb/s)
    • USB 2.0 (High-speed mód): 480 Mbps (60 Mb/s)
    • USB 3.0 (SuperSpeed mód): 5 Gbps (625 Mb/s)
    • USB 3.1 (SuperSpeed+ mód): 10 Gbps (1,25 Gb/s)
    • USB 3.2 (SuperSpeed+ mód): 20 Gbps (2,5 Gb/s)
  • Vezérlő(k): xhci_hcd, xhci-pci

Ezeknél léteznek még újabb és gyorsabb USB specifikációk is, de ezekkel most itt nem foglalkozunk.

 

 

USB eszközök megkeresése

Most, hogy már ismerjük az USB szabványokat, verziókat és vezérlőket, ebben a lépésben megkeressük a számítógépünkhöz csatlakozó USB eszközöket.

Eszközök felsorolása

A rendszerhez csatlakozó eszközöket elsősorban az lsusb paranccsal listázhatjuk ki:

lsusb
lsusb -t

A jobb áttekinthetőség kedvéért kétféleképpen is megjelenítjük a listát: az első parancs egy sima listát ad, majd a -t kapcsolóval pedig egy fa struktúrában jeleníti meg az eszközeinket:

USB eszközök kilistázása az lsusb parancs segítségével

Az USB hub-ok feladata a portjaikra történő eszközcsatlakoztatások és leválasztások figyelése, valamint az eszközök energiaellátása és energiagazdálkodása. Az USB gazdavezérlőnek, vagy állomásvezérlőnek (host controller) van egy beágyazott hub-ja, amelyet gyökérhubnak (root hub) hívnak. A számítógép hátoldalán látható USB portok a gyökérhub-ok portjai. Az USB gazdavezérlő feladata pedig az USB busz irányítása, valamint az eszközök és a gazdavezérlő közti kommunikáció lebonyolítása. Az eszközök egymás közti közvetlen kommunikációja nem támogatott.

Egy számítógép rendelkezhet akár több gazdavezérlő interfésszel (Host Controller Interface, HCI) is, valamint egy gazdavezérlő interfész kezelhet több buszt is, így lehetséges például, hogy a gépben lehet egyszerre több USB2-es (EHCI) port, és mellette USB3-as  (xHCI) portok is, stb.

Az első lsusb parancs kimenetében a sorszámokkal ellátott (00x) USB buszokat láthatjuk, az eszközsorszámokat (00y), az ID-ket (ffff:ffff, eszközazonosítók, erről majd később), valamint, a rajtuk kommunikáló eszközöket is, amelyek között mindegyik busz esetében a 001 eszközhelyen szerepelnek a fentebb említett speciális hubok, a gyökérhubok, valamint a többi csatlakozó eszközeik is, amelyeknek buszonként egyedi eszközsorszámuk van 002-től indulva csatlakozásuk alapján. Például ha kihúzzuk az egeret, majd visszacsatlakoztatjuk, akkor már egy magasab eszközsorszámot fog kapni. USB eszközök lehetnek például billentyűzetek, egerek, pendrive-ok, külső HDD-k, webkamerák, nyomtatók, stb, vagy akár további hub-ok is, amik segítségével tovább oszthatók az USB portok.

A kimenetben még az is látszik, hogy az adott busz éppen egy 1.1-es USB-t jelöl, vagy egy 2.0-ást. A laptopom példájában 4 busz van a gépben. Ezek között van 2 darab 1.1-es USB port és 2 darab 2.0-ás. A Linux rendszer érzékeli a felcsatlakoztatott eszköz szabványát (OHCI, UHCI, EHCI vagy xHCI), és a számára megfelelő buszra csatlakoztatja. Így például ahogy a képen is látható módon az egér a 003-as buszhoz (USB 1.1) csatlakozik a 30-as eszközhelyre, míg a külső merevlemez pedig a 001-es busz 018-as eszközhelyére csatlakozik, ami pedig USB 2.0 portokat működtet. Az persze más kérdés, hogy ez a külső meghajtó tudná az USB 3.0-ás szabványt is, csak a laptop nem rendelkezik USB3-as porttal, ezért erre csatlakoztatja. Tehát a csatlakoztatott eszközök helye nem számít, a Linux automatikusan az eszköz számára optimális buszhoz kapcsolja; még akkor is ugyanígy kerülnek felcsatlakoztatva, ha felcserélem az eszközök csatlakoztatási helyeit. Természetesen számít az USB port csatlakozó is a gépen, így például ha egy számítógépen vannak kék USB 3-as csatlakozók is, akkor azok tudják a sebességeket/szabványokat visszafelé is, ha egy lassabb eszköz kerül rácsatlakoztatva, viszont egy fekete csatlakozóba dugott eszköz nem fog tudni működni az USB3 sebességével, csak a vele megegyező, vagy lassabb sebességekkel.

A második, lsusb -t parancs kimenetében pedig láthatunk egy részletesebb listát, amiben az összes használatban lévő USB port megjelenik. Ezek az USB portok nem azonosak a külső fizikai portokkal és azok számaival, hanem ezek inkább amolyan logikai jelentőséggel bírnak, mivel a rendszer határozza meg, hogy például egy csatlakoztatott külső merevlemez vagy egér melyik busz melyik portjára kerül. Továbbá lehetnek belső eszközök is a listában, amik az alaplapon vannak kialakítva, tehát nem rendelkeznek külső portokkal, valamint az alaplapok is tartalmazhatnak még beépített hub-okat is, amikkel tovább szokták növelni a külső csatlakozási lehetőségek számát.

A példában tehát látszik, hogy itt van két gazdavezérlő interfész (Host Controller Interface), amelyikből az egyik az OHCI (Open Host Controller Interface), ami kezel két darab USB 1.x buszt, valamint van egy EHCI (Enhanced Host Controller Interface), ami pedig kezel további két USB buszt, amik 2.0-ás szabvánnyal, illetve sebességgel működnek. Így tehát ebben a gépben összesen van 4 busz, amikhez kapcsolódnak az eszközök, illetve kommunikálnak rajtuk. Ez természetesen számítógépenként eltérő, hogy milyen interfész szabványok vannak az alaplapján, vagy akár egy utólag behelyezett PCI USB bővítőkártyán, illetve hogy ezek hány buszt kezelnek, stb.

A kimeneti listában a Class értékeknél még láthatjuk azt is, hogy az adott USB portnak milyen funkciója van, pl. Video, Human Interface Device (billentyűzet, egér), stb; továbbá a Driver értékeknél jelenik meg az adott eszköz vezérlője is, pl. ohci-pci, ehci-pci, stb, amikről fentebb már írtam a felsorolásban, valamint a sorok végén pedig látszódnak az eszközök sebességei is, pl. 12M, 480M. Ezek is benne vannak a fenti felsorolásban (az Mbps értékeknél), hogy melyik szabvány milyen sebessége(ke)t tud maximálisan.

Ezek alapján az információk alapján tehát meg tudjuk határozni, hogy melyik eszközünk melyik gazdavezérlő interfészre csatlakozik, ebből pedig tudjuk, hogy az melyik USB verziót foglalja magában, melyik buszra illetve gyökérhubra csatlakozik. Itt még érdemes megjegyezni, hogy egy USB port csatlakoztatható az USB 3.x, 2.0 és az 1.x gyökérhubhoz is. Így ha például valamelyik USB 3.x gyökérhub meghibásodik, vagy lekapcsoljuk azt, akkor a rendszer automatikusan átcsatlakoztatja egy másik buszra/gyökérhubra, ami lehet egy másik 3.x gyökérhub (amennyiben több van), vagy éppen egy 2.0 vagy 1.x USB busz gyökérhubja is lehet. Ezzel lejjebb még foglalkozunk majd, mivel ez a mai feladatunk fő témája.

Részletes információk megtekintése

Lehetőség van arra is, hogy az USB eszközök teljes részleteit is megtekinthessük, amire az lsusb parancs -v (verbose) kapcsolója szolgál. Ezt a parancsot már root-ként futtassuk, mert eddig ugyan még nem volt különbség az lsusb parancs kimenete között sima felhasználó és root esetében, de itt már vannak olyan részek, amik sima felhasználóként futtatva nem jelennek meg. Tehát root-ként a parancsunk:

lsulb -v
Ennek a kimenete nagyon hosszú is lehet, attól függően, hogy hány USB eszköz csatlakozik a számítógépünkhöz. Mivel nálam is elég hosszú, ezért most ennek a kimenetét nem másolom ide.

Ha pedig csak egy adott USB eszköz részleteire vagyunk kíváncsiak, akkor megadhatjuk az USB busz sorszámát és az eszköz sorszámát is. A saját példámnál maradva, lekérdezem a külső merevlemezem részleteit, ami az első kimenet képe alapján az 1. busz 18. eszközsorszámán lenne elérhető, azonban a leírás készítése közben már volt laptop kikapcsolás, és külső HDD eltávolítás, újracsatlakoztatás, ezért azóta az eszköz sorszáma nálam a 22-re változott, ennek megfelelően tehát most ezt kérdezem le az lsusb parancs -s kapcsolójának segítségével:

lsusb -v -s 1:22

Itt tehát megmarad a -v kapcsoló, és hozzáadunk még egy -s kapcsolót is, aminek <busz sorszáma>:<eszköz sorszáma (Device)> formában adjuk meg a pontos eszközünket a lekérdezéshez. Ennek a kimenete pedig:

Bus 001 Device 022: ID 152d:0578 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x152d JMicron Technology Corp. / JMicron USA Technology Corp.
  idProduct          0x0578 JMS567 SATA 6Gb/s bridge
  bcdDevice            1.00
  iManufacturer           1 JMicron
  iProduct                2 USB3.0 External HDD
  iSerial                 3 0000AB12359B
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0055
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    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     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           4
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     98 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        Command pipe (0x01)
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        Status pipe (0x02)
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        Data-in pipe (0x03)
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        Data-out pipe (0x04)
Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength       0x0016
  bNumDeviceCaps          2
  USB 2.0 Extension Device Capability:
    bLength                 7
    bDescriptorType        16
    bDevCapabilityType      2
    bmAttributes   0x00000f0e
      BESL Link Power Management (LPM) Supported
    BESL value     3840 us 
  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          10 micro seconds
    bU2DevExitLat          32 micro seconds
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

Ez utóbbinak a kimenete értelemszerűen benne van az előző parancs kimenetében is, de így könnyen kiszűrhetjük a számunkra lekérdezni kívánt eszközöket külön.

Itt láthatjuk, hogy rengeteg információt kapunk az USB-s perifériánkról, amiből a mai feladatunk során csak néhánnyal lesz dolgunk.

 

 

Eszközazonosítók (ID-k)

Ahogy fentebb már említettem a legelső parancs kimenetének értelmezésében, ott még láthattunk ID-ket is. Ezek nem létfontosságú adatok ennek a mai feladatunknak a szempontjából, csak érdekességképpen érdemes néhány szót ejteni róla.

Az ID-k, ahogy a korábbi képen is látszódik, két darab 4 hexadecimális számjegyből álló értéket jelenítenek meg (2x16 bit), amiket kettőspont választ el. Minden hardvereszköznek van egy saját ID-je, ami pontosan beazonosítja azt. Ennek megfelelően tehát ennek a számnak az első része jelenti az USB hardvereszköz gyártójának azonosítóját, a kettőspont utáni része pedig a típusát.

Ha tehát a kép alapján megnézzük a "152d:0578" számot ami a külső HDD-m azonosítója , akkor ebben a részletes kimenetben is találkozunk ezekkel:

  idVendor           0x152d JMicron Technology Corp. / JMicron USA Technology Corp.
  idProduct          0x0578 JMS567 SATA 6Gb/s bridge

Ebben a két sorban látszik jól, hogy a szám első része (152d) a gyártó azonosító (idVendor mező), a második része (0578) pedig a típust jelöli (idProduct). Itt a "0x" előtagok csak a számok hexadecimális mivoltára utalnak.

A példában szereplő külső HDD meghajtó egy 3,5"-os SATA-s notebook winchester, ami egy USB 3-as tokban van, így a rendszer ezt a tokot (USB/SATA híd) érzékeli, illetve ennek a gyártójának illetve típusának számát jeleníti meg.

Ezek az információk például akkor jöhetnek jól, ha mondjuk scriptet írunk valamilyen USB-vel kapcsolatos automatizációs feladathoz, amiben meg kell keresnünk egy konkrét USB-s hardvereszközt úgy, hogy az bármikor bármelyik buszon illetve porton is előfordulhat. Például, ha mondjuk a rendszerünkre csatolásra kerül a külső HDD-nk, akkor indítsa el a napi mentést, stb. Ha pedig egy másik meghajtó kerül csatlakoztatásra, akkor mást mentsen rá, stb. Persze az ilyen típusú feladatokat a blokk eszköznevek, címkék és a csatolási pontok figyelésével is meg lehet oldani, de ha valami ok miatt mégis egy konkrét hardvereszközt akarunk figyelni akár más célokból, akkor jól jöhetnek ezek a dolgok.
Sorozatszámok (iSerial-ok)

A sorozatszámok, vagyis a részletes kimenetekben szereplő "iSerial" mezők jelentősége már sokkal fontosabb.

A fenti külső HDD példánál maradva, annak az iSerial értéke, természetesen ezt is root-ként futtatva: 

lsusb -v -s 1:22 | grep "iSerial"

Illetve még érdemes kibővíteni pár mezővel, hogy átfogóbb adatokat kaphassunk a lekérdezett eszközről:

lsusb -v -s 1:22 | grep -E  "iSerial|idProduct|iProduct"

Így megjelenik az iSerial szám is, és felette a hardvereszköz leírása is, így nem keverhetjük össze véletlenül más eszközzel:

USB eszköz részleteinek lekérdezése az lsusb paranccsal

Itt láthatjuk a lekért adatokat: idProduct, iProduct és iSerial. Az alatta megjelenő hibaüzenettel nem kell foglalkozni.

Az iSerial értéket nézve itt láthatunk egy 3-as számjegyet, ami nem lényeges, hanem utána egy hosszú hexadecimális számot. Ez az eszköz sorszáma. De mi történik, ha nem egy külső HDD-t, vagy egeret kérdezünk le, hanem az azokat kezelő gyökérhubot?

Mint ahogy fentebb már említettem, a gyökérhubok (root hub) a gazdavezérlők, vagy állomásvezérlők (Host Contoller) speciális, beágyazott hub-jai, amik minden esetben az adott busz 1-es eszközhelyein foglalnak helyet. Ha tehát ennek megfelelően lekérdezzük a fentebbi HDD-t működtető gyökérhub adatait az előbbi példához hasonlóan:

lsusb -v -s 1:1 | grep -E  "iSerial|idProduct|iProduct"
  idProduct          0x0002 2.0 root hub
  iProduct                2 EHCI Host Controller
  iSerial                 1 0000:00:04.1

USB gyökérhub adatainak lekérdezése

Itt láthatjuk, hogy a már a leírás korábbi részében is említett USB 2.0-ás gyökérhub adatai jelennek meg, ami egy EHCI (Enhanced Host Controller Interface) gazdavezérlő interfészt foglal magában. Ennek az iSerial száma pedig más, mint a korábban látott külső HDD iSerial száma.

A gyökérhuboknak tehát a következő formátumú iSerial számuk van: 0000:00:00.0, ami megegyezik a PCI buszok (Peripheral Component Interconnect) címzési rendszerével. Ez már szorosabban kapcsolódik a mai téma további részeihez.

 

 

Külső tárolóeszköz kikapcsolása, logikai leválasztása

Mivel ennek a leírásnak a fő témája az, hogy a kikapcsolt USB-s tárolóeszközöket hogyan tudjuk újraindítani, ezért előbb le is kell kapcsolni azokat ahhoz, hogy majd később visszakapcsolhassuk őket. Ebben a fejezetben ezért most teszünk egy rövid kitérőt, amiben lekapcsolom a külső HDD-met. Ezt meg lehet tenni a grafikus felületen is a tálcán a biztonságos eltávolítás funkcióval, vagy parancssorból. Előbb viszont nézzük meg a listákat az USB eszközökkel és a blokk eszközökkel, még a lekapcsolás előtt, mert majd szükségünk lesz a bekapcsolás során pár dologra innen:

lsusb
lsusb -t
lsblk

Az USB és a blokk eszközök listája a külső HDD-vel

Itt tehát láthatjuk, hogy az USB listában szerepel a külső háttértár a 001-es sorszámú busz 022-edik sorszámú eszközeként – ami egy 2.0-ás (EHCI) USB busz –, valamint a blokk eszközök listájában is szerepel a külső háttértár a /dev/sdb eszköznéven, amiben a /dev/sdb1 partíció fel is van csatolva egy könyvtárba. Először tehát lecsatoljuk root-ként a partíciót, majd kikapcsoljuk a winchestert az udisksctl paranccsal:

umount /dev/sdb1
udisksctl power-off -b /dev/sdb

Lényegében ugyanezt hajtja végre a rendszer, ha a grafikus felületen választjuk le az USB-s háttértárakat. A winchester leállt, a LED is kikapcsolt a tokján.

Itt természetesen ügyeljünk a pontos eszköznévre.

Ezután újra lekérjük a listákat, és megnézzük a változásokat:

lsusb
lsusb -t
lsblk

Az USB és a blokk eszközök listája a külső HDD kikapcsolása után

A friss listákból eltűnt az USB eszközünk, valamint a blokk eszközök közül is eltűnt a /dev/sdb is az egy szem partíciójával. Tehát ezt már normál esetben nem tudnánk újra felcsatolni a mount paranccsal, csak ha kihúznánk a gépből, majd újra csatlakoztatnánk. De mivel ez a leírás éppen erről szól, hogy hogyan indíthatjuk újra a külső HDD eszközünket a fizikai újracsatlakoztatás nélkül, ezért a következő fejezetben az USB gyökérhubok tájékán nézünk körül.

 

USB gyökérhubok megkeresése, kezelése, újraindítása

Ebben a fejezetben az USB gyökérhubokkal (root hub) foglalkozunk. Első körben szükséges őket pontosan beazonosítanunk, mert általában egy számítógépben több USB busz, illetve gyökérhub is működhet, ezért nem mindegy, hogy melyiket találjuk meg.

Az USB rendszer az asztali számítógépben/laptopokban a nagy sebességű PCI/PCIe buszhoz kapcsolódik. Persze lehetnek olyan architektúrák, ahol ez másképpen működik, de a hagyományos asztali PC-k és laptopok esetén a PCI buszhoz kapcsolódik. Ezért itt röviden érintjük a PCI buszok címzési rendszerét, hogy érthető legyen a többi rész is.

PCI buszok címzése

Itt röviden megemlítjük, hogy hogyan is néz ki a PCI buszok címzési rendszere, ami ahhoz szükséges, hogy megtaláljuk a megfelelő USB buszunkat és gyökérhubunkat.

Korábban már esett szó az USB részletes adatainak lekérdezésénél az iSerial mező értékéről, ahol egy normális USB-s eszköz esetén található az eszköz egyedi sorszáma, de az USB gyökérhuboknál pedig ebben a mezőben egy PCI busz címzés található, ami a számítógépben egyértelműen beazonosítja az USB gyökérhubot.

Ennek a számnak a formátuma, ahogy már korábban is említettem tehát: 0000:00:00.0. Ezek hexadecimális számok, amiknek a jelentése:

  • 0000:00:00.0: Domain, azaz a PCI busz címtartománya. Ezzel nem kell különösebben foglalkoznunk, ez 4 darab 0
  • 0000:00:00.0: Busz. Ez nem összetévesztendő az USB buszokkal, hanem ez a PCI busz sorszámát jelenti. 8 bites érték, 256 lehetséges buszt kezelhet.
  • 0000:00:00.0: Device. Azaz a PCI eszköz sorszáma. 5 bites érték, azaz 32 eszköz lehet buszonként.
  • 0000:00:00.0: Funckió. Ez pedig 3 bites érték, tehát 8 féle funkció lehet egy eszközhelyen.

Ebbe jobban nem szükséges belemennünk, hogy ne kanyarodjunk el az USB rendszertől, ezért inkább lássuk ezeket a címzéseket az USB-k esetében a gyakorlatban.

Az lspci parancs segítségével kilistázhatjuk a számítógépünkben lévő PCI eszközöket. Ezek között most rákeresünk a grep paranccsal az USB eszközökre:

lspci | grep "USB"

Itt felsorolja a kimenetben az USB kontrollereinket, illetve a gyökérhubokat, amik előtt láthatjuk a PCI címzéseket is. Illetve itt még nem a teljes címeket látjuk, hiányoznak a domain-ek, azaz a címtartományok. Ezeket pedig a -D kapcsolóval jeleníthetjük meg:

lspci -D | grep "USB"

Így már teljes a kép, a teljes címek láthatók az USB kontrollerek sorai elején:

USB eszközök listázása az lspci paranccsal

Itt is látható, hogy ebben a gépben van 4 darab USB busz, illetve gyökérhub, amik a megjelenített PCI busz címeken helyezkednek el. Itt mind a 4 USB busz a 0-ás PCI buszhoz kapcsolódik.

 

 

Érdekességképpen ha kilistázzuk az összes eszközt, akkor láthatjuk, hogy a többi hardver hova kapcsolódik:

lspci -D

Összes PCI eszköz kilistázása

Itt tehát ezen a gépen majdnem minden hardver a 0-ás PCI buszon van, kivéve az Nvidia videokártyát, ami a 2. buszon van, illetve a WLAN eszközt, ami pedig az 5. buszon van.

Visszakanyarodva az USB eszközökhöz, megnézzük, hogyan találjuk meg a megfelelő USB gyökérhubot a kikapcsolt eszközünk újraindításához.

A megfelelő USB gyökérhub megkeresése

Az eddigi elméleti részek alapján már gyorsan meg tudjuk találni a bekapcsolni kívánt eszközünket működtető gyökérhubot.

Első körben még az HDD-nk vagy pendrive-unk bekapcsolt állapotában kilistázzuk az USB eszközöket az lsusb paranccsal:

lsusb

Itt megkeressük a kérdéses tárolóeszközt, amit majd később újra szeretnénk tudni indítani fizikai újracsatlakoztatás nélkül, és megjegyezzük, hogy melyik USB buszhoz csatlakozik. 

A példa kedvéért most újracsatlakoztattam a külső HDD-t. Így tehát nálam a friss kimenet:

USB eszköz és busz megkeresése

Itt ez a külső tárolóeszköz az 1. USB buszhoz csatlakozik a 28-as eszközhelyen. Az 1. busz pedig egy 2.0-ás EHCI (Enhanced Host Controller Interface) USB vezérlő. A meghajtó fel is van csatolva egy könyvtárba, tehát használatra kész.

Ezután kikapcsoljuk az eszközt, illetve szoftveresen eltávolítjuk. Ezt a tálcán is megtehetjük, vagy a parancssorból a blokk eszköznév segítségével. Nálam:

umount /dev/sdb1
udisksctl power-off -b /dev/sdb
Itt figyeljünk a pontos nevekre. Az umountnál az eszközön lévő partíciót kell megadni (sdXY), míg az eszköz kikapcsolásánál pedig magát a fő eszköznevet (sdX) adjuk meg.

Ezután újra listázzuk a dolgokat, hogy lássuk, hogy tényleg eltűnt mindenhonnan a külső HDD-nk:

lsusb
lsblk

USB és a blokk eszközök listázása a külső HDD kikapcsolása után

És látjuk, hogy eltűnt mindenhonnan a meghajtónk.

A kiindulási pontunk tehát ez. Amíg nem húzzuk ki fizikailag is az eszközt, és másikat sem csatlakoztatunk közben mellé, addig biztosan nem fog megváltozni a busz, amire csatlakozik, tehát ezzel a busz sorszámmal később bármikor visszakapcsolhatjuk a rajta lévő eszközeinket.

Ezután kiolvassuk az USB buszunk iSerial értékét. Az iSerial értéket a gyökérhub lekérdezésével olvashatjuk ki, ami pedig a megfelelő buszunk 1. eszközhelyére kapcsolódik. A parancs tehát:

lsusb -v -s 1:1 | grep -E  "iSerial|idProduct|iProduct"

USB gyökérhub iSerial értékének azaz a PCI busz címének a kiolvasása.

Itt több adatot is lekértünk, hogy kisebb legyen a tévesztési lehetőség.

Az 1. USB buszunk, illetve gyökérhubunk iSerial értéke, azaz a PCI buszokon belül elfoglalt helyének pontos címe: 0000:00:04.1.

 

 

USB gyökérhubok ki- és bekapcsolása

Az USB gyökérhub-ok ki- és bekapcsolásával elérjük, hogy a rendszer újra táppal látja el az adott gyökérhub minden portját, így a rajtuk lévő, esetlegesen kikapcsolt eszközök is újra elindulnak, mintha fizikailag újracsatlakoztattuk volna őket.

Mint sok más hardvereszközt is, az USB gyökérhub-okat is a Linux rendszer fájlrendszerében érhetjük el.

A PCI eszközök vezérlőihez a /sys/bus/pci/drivers/ könyvtárban férhetünk hozzá. Ha ide belépünk, és kilistázzuk a könyvtár tartalmát, akkor láthatunk sok eszköz vezérlőt, amiket a gépünk használ:

cd /sys/bus/pci/drivers
ls -al

PCI driverek listázása

Ezek közül nekünk most csak az USB Host Controller Interface eszközök vezérlői lényegesek, tehát amiket az elején felsoroltam a különböző szabványok vezérlőinél. Ebben a gépben például csak USB 1.1 és USB 2.0 van, ennek megfelelően itt ezek között megtalálhatjuk az ohci-pci és az ehci-pci könyvtárakat. De ha a gépben lennének USB 3.x portok is, akkor itt lenne egy xhci_hcd vagy egy xhci-pci könyvtár is. Ezek a könyvtárak tartalmazzák azokat a szimbolikus linkeket és fájlokat, amik kapcsolatban vannak az USB Host Controllerekkel.

Itt válasszuk ki a megfelelő vezérlőt, ami kezeli a megfelelő USB gyökérhub-unkat, és lépjünk be a könyvtárába. Nálam tehát ez az EHCI (Enhanced Host Controller Interface), így ennek megfelelően az ehci-pci könyvtár lesz a megfelelő:

cd ehci-pci
ls -al

Természetesen mindenki a saját root hub-jának megfelelő vezérlő könyvtárba lépjen be, amit korábban az lsusb parancs is megjelenített.

Az ehci-pci könyvtár listázása

A korábbi elméleti részek után már könnyen érthető, hogy ez az EHCI gazdavezérlő ezen a gépen 2 darab buszt működtet, és rajtuk 2 darab gyökérhubot, amik ugye a 2.0 szabvánnyal működnek. Ezek közül a fentebb kiolvasott PCI busz címünk is megvan, mégpedig a 0000:00:04.1, ami itt egy szimbolikus link formájában van jelen, ez hivatkozik a rendszerben a megfelelő eszköz vezérlőre. A másik címen pedig az EHCI gazdavezérlő másik busza található, amivel most nem foglalkozunk.

Érdekességképpen, ha ki szeretnénk listázni az összes USB busz/gyökérhub címét, ami a számítógépünkben működik, akkor ezt az alábbi paranccsal tehetjük meg:

find /sys/bus/pci/drivers -type l -name "0000:*" | grep -E "(oh|uh|eh|xh)ci"

Ez kiadja az összes lehetséges "0000:" kezdetű symlinket, amik a különböző gazdavezérlő könyvtárakban vannak.

Összes USB gyökérhub kilistázása

Itt látszódnak a fájlok útvonalaiban a vezérlő könyvtárak, és a bennük lévő vezérlők linkjei.

Visszatérve az imént kilistázott könyvtárra, itt az USB root hub-ok linkjein kívül van még két lényeges fájlt, ezek pedig a bind és unbind nevű fájlok. Ezeket nem lehet olvasni csak írni, azt is csak a tulajdonosa által, ami a root. A fájlok úgy működnek, hogy amilyen PCI címet, azaz USB gyökérhub címet "beledobunk", azzal csinál valamit. Konkrétan tehát ha a címet beleírjuk az unbind fájlba, akkor lekapcsolja az adott USB buszt/gyökérhubot, ha pedig a bind fájlba írjuk bele, akkor pedig felkapcsolja. Mindezt lássuk a gyakorlatban.

Először kilistázom a könyvtárat, az USB eszközöket és a blokk eszközöket ismét, hogy láthassuk a különböző állapotokat a kapcsolgatás közben is:

ls -al
lsusb
lsusb -t
lsblk

Ezután fogom a már korábban kikeresett USB gyökérhub címemet, és beleírom az unbind fájlba:

echo "0000:00:04.1" > unbind

USB gyökérhub lekapcsolása

Ezután a külső HDD-n elkezd villogni a LED, a winchester elindul, majd a gépen megjelenik a szokásos "Új hordozható adathordozó észlelve" ablak, mint amikor fizikailag csatlakoztatjuk az eszközt.

De nézzük meg, hogy mi is történik a háttérben, hiszen most lekapcsoltuk a gyökérhub-ot, így ez elsőre nem lenne logikus működés.

Tehát újra lekérdezem az előbbieket:

ls -al
lsusb
lsusb -t
lsblk

USB és eszközállapotok a gyökérhub lekapcsolása után

Így már érthető a dolog:

Az egyik USB gyökérhub-unk teljesen eltűnt: a könyvtárból is eltűnt a szimbolikus linkje, valamint az USB listából is lekerült, aminek az 1-es sorszáma volt. Csak a 2-3-4 számú gyökérhub van jelen, és ezek közül a 3-as számú buszra/gyökérhubra csatlakoztatta fel a külső HDD eszközt, amit ha jobban megnézünk, akkor az egy 1.1-es USB gazdavezérlő működtet (OHCI). Valamint lejjebb pedig a blokk eszköznév is előkerült (/dev/sdb), amit fel is csatolt, ahogy kell. Viszont most még nem a megfelelő USB buszon van az eszközünk. Tehát ezek alapján látható, hogy a rendszer ilyenkor átcsatlakoztatja az összes eszközt, ami a lekapcsolt buszon volt egy másik, működő buszra. Ezt a rendszer dönti el, hogy hova kerülnek. Jelen esetben az egyik 1.1-es USB buszra kapcsolta át. Fentebb erről már volt szó, hogy ha kiesik egy busz, akár meghibásodás miatt, vagy mert lekapcsolják, akkor ez történik, mint ami most is: a rajta lévő eszközök átkerülnek egy másik működő buszra.

Ezután kapcsoljuk vissza az imént lekapcsolt USB buszunkat/gyökérhubunkat most a bind fájlba történő írással:

echo "0000:00:04.1" > bind

Majd ezután kérdezzünk le ismét mindent:

ls -al
lsusb
lsusb -t
lsblk

USB gyökérhub visszakapcsolása és az állapotok lekérdezése

A meghajtó tokján a LED ismét villogni kezd, majd az asztalon előkerül egy újabb "Új hordozható adathordozó észlelve" ablak.

Ha pedig az eszközöket megnézzük, akkor ismét előkerült a szimbolikus link is a gyökérhub címével, valamint az USB eszközök listáján is újra megjelent az 1-es sorszámú USB 2.0-ás busz, aminek a 3. eszközhelyén van a külső HDD. A blokk eszközöknél pedig nincs változás, ugyanúgy ott a blokk eszköz felcsatolva ugyanabba a könyvtárba.

Ezzel tehát pontosan ugyan az történt, mintha kihúztuk volna a külső eszközt és újracsatlakoztattuk volna.

Természetesen vegyük figyelembe, hogy ha ugyanezen a buszon még több másik eszköz is van, akkor ez a busz/gyökérhub újraindítás hatással lesz mindegyikre. Mert lekapcsoláskor minden eszköz átkerül egy másik buszra, majd visszakapcsoláskor pedig vissza az eredeti helyükre. Így tehát ha például közben van egy másik tárolóeszközünk, amin éppen olvasási vagy írási művelet zajlik, akkor eközben ne kapcsoljuk le az USB buszt, mert előforduhat, hogy adatvesztés lehet a másik eszközön. Tehát mindezt akkor hajtsuk végre, ha biztosak vagyunk benne, hogy a lekapcsolni kívánt buszon nincs semmi olyan eszköz, ami érzékeny az újraindításra. De ha például egy egérről vagy billentyűzetről van szó, akkor azokat nem zavarja egy ilyen ki- és bekapcsolás.

 

 

Konklúzió

Ezzel a módszerrel kapcsolgathatjuk ki és be számítógépünk USB buszait, illetve gyökérhub-jait, aminek köszönhetően újraindíthatjuk a rajtuk lévő eszközöket anélkül, hogy fizikailag újra kellene csatlakoztatni azokat.