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:
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
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.
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:
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
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
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
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:
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
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:
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
Ezután újra listázzuk a dolgokat, hogy lássuk, hogy tényleg eltűnt mindenhonnan a külső HDD-nk:
lsusb
lsblk
É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"
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
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.
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.
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
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
Í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
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.
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.
- Hogyan küszöbölhetjük ki a "Not authorized to perform operation" hibaüzenetet a pendrive-ok és egyéb külső USB tárolóeszközök automatikus felcsatolásakor
- en.wikipedia.org - USB
- docs.oracle.com - USB Host Controller and Root Hub
- wiki.xenproject.org - wiki - Bus:Device.Function (BDF) Notation
- renenyffenegger.ch - notes - hardware - PCI
- linux.org - threads - resetting-the-usb-subsystem
- A hozzászóláshoz regisztráció és bejelentkezés szükséges
- 651 megtekintés