This shows you the differences between two versions of the page.
so2:laboratoare:lab12:exercitii [2018/05/16 00:14] razvan.deaconescu [[1p] BONUS: Completare formular de feedback] |
so2:laboratoare:lab12:exercitii [2019/05/20 14:32] (current) razvan.deaconescu [1. [2p] Implementare bus] |
||
---|---|---|---|
Line 103: | Line 103: | ||
===== Completare formular de feedback ===== | ===== Completare formular de feedback ===== | ||
- | Apreciem opinia voastră legată de activitățile cursului de SO2. Ne ajută să îmbunătățim cursul și să facem materia cât mai accesibilă și interesantă. Pentru această vă rugăm să completați [[http://cs.curs.pub.ro/2017/blocks/feedbackacs/stats.php?courseid=144&blockid=2391|formularul de feedback de pe cs.curs.pub.ro]] (trebuie să fiți autentificați și înrolați în cadrul cursului). Vă mulțumim! | + | Apreciem opinia voastră legată de activitățile cursului de SO2. Ne ajută să îmbunătățim cursul și să facem materia cât mai accesibilă și interesantă. Pentru această vă rugăm să completați [[https://acs.curs.pub.ro/2018/course/view.php?id=295|formularul de feedback de pe cs.curs.pub.ro]] (trebuie să fiți autentificați și înrolați în cadrul cursului). Vă mulțumim! |
- | ===== [6.5p] Linux Device Model ===== | + | |
- | În prima parte ne propunem să ne familiarizăm cu modelul ''Linux Device Model'' și reflectarea acestuia în userspace prin intermediul sistemului virtual de fișiere ''sysfs''. Vom analiza implementarea magistralelor și modul în care device driverele se conectează la o magistrală. Pentru început, vom lucra cu o magistrală virtuală, definită în modulul ''mybus.ko'' din subdirectorul ''virtual_bus/mybus/'' la care vom atașa driverul ''mydriver.ko'' din subdirectorul ''virtual_bus/mydriver''. | + | ==== 1. [2p] Implementare bus ==== |
+ | |||
+ | Analizați conținutul fișierului ''bex.c'', care conține implementarea unui driver de magistrală. Urmăriți comentariile marcate cu ''TODO 1'' pentru a implementa părțile ce lipsesc: înregistrați driverul de magistrală și adăugați un nou device, numit ''root'', cu tipul ''none'' și versiunea ''1''. | ||
<note tip> | <note tip> | ||
- | În rezolvarea acestui exerciţiu vă veţi întâlni cu: | + | Aruncați o privire pe implementarea funcției ''bex_add_dev()''. |
- | * ''my_bus_type''(mybus.c): variabilă globală pentru tipul de magistrală | + | |
- | * ''my_bus_device''(mybus.c): variabilă globală pentru dispozitivul magistralei | + | |
- | * ''my_device''(virtual_bus.h): structură folosită pentru dispozitivele ce se conectează la magistrală | + | |
- | * ''my_driver''(virtual_bus.h): structură folosită pentru driverul care lucrează cu dispozitivele ce se conectează la magistrală | + | |
- | * ''dev_data''(mydriver.c): variabilă globală ce menţine datele necesare driverului | + | |
</note> | </note> | ||
- | ==== 1. [1p] Implementare magistrală ==== | ||
- | |||
- | Intrați în directorul ''virtual_bus/mybus'', unde găsiți implementarea unei magistrale ''mybus'', așa cum este descrisă în laborator. Analizați conținutul fișierelor ''mybus/mybus.c'' și ''include/virtual_bus.h''. | ||
- | Observaţi că la încărcarea modulului se înregistrează atât o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L109|bus_type]], reprezentând tipul de magistrală, cât și o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|device]], reprezentând dispozitivul efectiv al magistralei. | ||
- | |||
- | Compilați și inserați modulul. | ||
- | Verificaţi că tipul de magistrală apare în /sys/bus, iar dispozitivul în /sys/devices. | ||
- | Scoateți modulul şi observaţi că intrările din sysfs sunt înlăturate. | ||
- | |||
- | Modificați sursa astfel încât intrările pentru magistrală și dispozitivul asociat să fie ''virtualbus'', respectiv ''virtualbus0''. | ||
<note tip> | <note tip> | ||
- | Recitiți secțiunile [[:so2:laboratoare:lab12#magistrale|Magistrale]] și [[:so2:laboratoare:lab12#dispozitive|Dispozitive]] din laborator. | + | Înregistrarea și deînregistrarea o faceți folosind respectiv funcțiile ''bus_register()'' și ''bus_unregister()''. |
</note> | </note> | ||
- | Pentru verificare trebuie să se fi creat pe mașina virtuală în ''/sys'' intrările aferente magistralei (''virtualbus'') și dispozitivului părinte (''virtualbus0''):<code> | + | Compilați, copiați modulul pe mașina virtuală, încărcați-l în kernel și verificați faptul că dispozitivul de tip magistrală este vizibil în ''/sys/bus''. De asemenea, verificați că dispozitivul este vizibil în ''/sys/bus/bex/devices.''. |
- | # ls /sys/bus/virtualbus/ | + | |
- | # ls /sys/devices/virtualbus0/ | + | |
- | </code> | + | |
- | ==== 2. [2p] Conectare driver la magistrală ==== | + | Eliminați modulul și observați că intrările din ''sysfs'' sunt eliminate. |
- | Intrați în directorul ''virtual_bus/mydriver'', unde găsiți implementarea unui device driver de tip caracter. | + | ==== 2. [2p] Adăugare atribute pentru tip și versiune ==== |
- | Modificați sursa astfel încât să respecte modelul ''Linux Device Model''. Dispozitivul ''echo'' se va conecta la magistrala virtualbus de la exercițiul anterior, având un driver asociat ''echo''. Numele driverului și al dispozitivului trebuie să fie identice. | + | Adăugați două atribute read-only: ''type'' și ''version''. Urmăriți comentariile marcate cu ''TODO 2''. |
- | + | ||
- | Urmăriți comentariile ''TODO 2'' din cod și exemplele de înregistrare dispozitiv/driver din laborator: [[:so2:laboratoare:lab12#dispozitive|înregistrare dispozitiv]], [[:so2:laboratoare:lab12#drivere|înregistrare driver]]. | + | |
- | + | ||
- | Pentru a vă conecta la magistrala ''virtualbus'', va trebui să folosiți funcțiile și tipurile de driver/device exportate de aceasta. | + | |
- | + | ||
- | În structura ''struct my_device_data'' adăugați un câmp de tipul ''struct my_device'' (tip de date definit în ''include/virtual_bus.h''). Câmpurile structurii ''my_device'' vor fi inițializate în funcția ''my_init''. | + | |
- | + | ||
- | Definiți o variabilă de tipul ''struct my_driver'' şi inițializați pentru aceasta modulul şi numele driver-ului. Înregistraţi driverul în funcţia ''my_init''. | + | |
<note tip> | <note tip> | ||
- | Parcurgeți secțiunea [[:so2:laboratoare:lab12#drivere|Drivere]] din laborator. Urmăriți exemplele de cod. | + | Va trebui să adăugați cele două atribute ''type'' și ''version'' în structura ''bex_dev_attrs'' pe modelul: |
+ | <code> | ||
+ | &dev_attr_<insert-attribute-type-here>.attr, | ||
+ | </code> | ||
</note> | </note> | ||
- | <note tip> | + | Observați că cele două atribute noi sunt vizibile în ''/sys/bus/bex/devices/root''. Verificați conținutul acestor atribute. |
- | Trebuie să înregistrați / deînregistrați variabilele de tipul ''struct my_device'' și ''struct my_driver'' în funcția de init / exit a modulului. Pentru aceasta folosiți funcțiile ''my_register_driver'' / ''my_unregister_driver'', respectiv ''my_register_device'' / ''my_unregister_device'', definite în fișierul ''mybus.c''. | + | |
- | </note> | + | |
- | <note tip> | + | O implementare pentru funcția de afișare de type este |
- | Pentru a transmite primul argument (magistrala) funcției ''bus_find_device'' folosiți o expresie de forma ''mydriver.driver.bus''. | + | |
- | </note> | + | |
- | În cadrul funcţiei ''my_init'', iniţializaţi dispozitivul şi înregistraţi-l. Vor trebui completate cel puțin câmpurile ''name'' și ''driver''. | + | <code c> |
+ | static ssize_t | ||
+ | type_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
+ | { | ||
+ | struct bex_device *bex_dev = to_bex_device(dev); | ||
+ | |||
+ | return sprintf(buf, "%s\n", bex_dev->type); | ||
+ | } | ||
+ | DEVICE_ATTR_RO(type); | ||
+ | </code> | ||
+ | ==== 3. [2p] Adăugare atribute del și add ==== | ||
- | De asemenea, puteți stoca un back pointer către ''struct my_device_data'' în câmpul ''%%dev->p->driver_data%%''. Acest câmp e util pentru a putea accesa datele private (''my_device_data'') ale dispozitivului și din locurile în care aveți acces doar la structura generică [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|struct device]]. Fiind un câmp din [[http://elixir.free-electrons.com/linux/v3.13/source/drivers/base/base.h#L73|datele private]] ale dispozitivului, pentru a accesa ''%%dev->p->driver_data%%'' e recomandat să folosiți funcțiile (interfața) [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L920|dev_set_drvdata]], [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L915|dev_get_drvdata]]. | + | Adăugați două atribute write-only, numite ''del'' și ''add''. ''del'' așteaptă un nume de device pentru a îl elimina, iar ''add'' așteaptă numele, tipul și versiunea pentru a crea un device nou. Urmăriți comentariile marcate cu ''TODO 3''. |
<note tip> | <note tip> | ||
- | Parcurgeți secțiunea [[:so2:laboratoare:lab12#dispozitive|Dispozitive]] din laborator. Urmăriți exemplele de cod. | + | Va trebui să adăugați atributele ''del'' și ''add'' în structura ''bex_bus_attr'' pe modelul: |
- | </note> | + | |
- | + | ||
- | Compilaţi modulul şi copiaţi-l pe maşina virtuală, împreună cu modulul de la exerciţiul anterior. | + | |
- | + | ||
- | <note warning> | + | |
- | Pentru a elimina warning-urile legate de nedefinirea funcțiilor de înregistrare/deînregistrare de dispozitiv, compilați ambele module din directorul părinte. Aveți în vedere să inserați modulul de la pasul anterior (''mybus.ko'') înaintea inserării modulului curent. | + | |
- | </note> | + | |
- | + | ||
- | Pentru testare urmăriți intrările de dispozitiv (''echo'') și de driver (''echo'') în ''/sys'' pe mașina virtuală: | + | |
<code> | <code> | ||
- | # ls /sys/bus/virtualbus/devices/ | + | &bus_attr_<insert-attribute-name-here>.attr, |
- | # ls /sys/bus/virtualbus/drivers/ | + | |
- | # ls /sys/devices/virtualbus0/ | + | |
</code> | </code> | ||
- | ==== 2.1. [1.5p] Informații device-uri de pe magistrală ==== | + | </note> |
- | + | ||
- | La sfârșitul inițilizării modulului ''mydriver'' (TODO 2.1), verificați dacă device-ul a fost atașat la magistrală. Pornind de la magistrala asociată, parcurgeți device-urile atașate și căutați-l pe cel cu numele ''echo''. Afișați numele device-ului, dacă acesta a fost găsit. | + | |
<note tip> | <note tip> | ||
- | Pentru căutarea unui dispozitiv folosiți funcția [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/bus.c#L371|bus_find_device_by_name]]. Transmiteți ''NULL'' ca al doilea argument al funcției. | + | Folosiți ''sscanf'' pentru a parsa inputul de la ''sysfs'' și ''bex_del_dev()'' and ''bex_add_dev()'' pentru a șterge și crea un device nou. |
+ | </note> | ||
- | Obțineți structura de tip magistrală (''struct bus_type'') printr-o construcție de forma ''my_driver.driver.bus''. | + | Un exemplu de funcție de tipul ''store'' este: |
- | Numele device-ului întors de funcția [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/bus.c#L371|bus_find_device_by_name]] se poate obține cu funcția [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L868|dev_name]]. | + | <code c> |
- | </note> | + | static ssize_t |
+ | add_store(struct bus_type *bt, const char *buf, size_t count) | ||
+ | { | ||
+ | char type[32], name[32]; | ||
+ | int version; | ||
+ | int ret; | ||
- | Pentru verificare la inserarea modulului se va afișa mesaj cu numele dispozitivului. | + | ret = sscanf(buf, "%31s %31s %d", name, type, &version); |
+ | if (ret != 3) | ||
+ | return -EINVAL; | ||
- | ==== 3. [2p] Atribute device drivere ==== | + | return bex_add_dev(name, type, version) ? : count; |
+ | } | ||
+ | BUS_ATTR(add, S_IWUSR, NULL, add_store); | ||
+ | </code> | ||
- | Extindeți driverul echo de la exercițiul anterior prin adăugarea unui atribut ''myattr'' pentru dispozitivul creat, ce va conține majorul și minorul dispozitivului (''major:minor''). Acest atribut va fi expus prin interfaţa ''sysfs'' din directorul device-ului ''echo''. | + | Creați un device nou și verificați dacă este vizibil în ''/sys/bus/bex/devices''. Eliminați-l și verificați că a dispărut din ''sysfs''. |
- | + | ||
- | Urmăriți comentariile ''TODO 3'' din cod. | + | |
<note tip> | <note tip> | ||
- | Va trebui să declarați și să înregistrați o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L549| device_attribute]]. Puteți folosi macro-ul [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L575|DEVICE_ATTR]] ce va crea o structură cu numele ''dev_attr_##_name'', unde ''##_name'' este numele atributului. | + | Folosiți ''echo'' pentru a scrie în atributele magistralei: |
- | Pentru folosirea macro-ului va trebui să specificaţi, în această ordine: | + | |
- | * numele atributului | + | |
- | * permisiunile la acces la intrarea din sysfs aferentă atributului; folosiţi valoarea ''0444''. | + | |
- | * o funcție [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L551|show]] ce afișează valoarea atributului pornind de la informațiile din [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|struct device]]. | + | |
- | * o funcţie [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L553|store]], care în cazul vostru poate fi ''NULL''. | + | |
- | În funcţia [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L303|show]], puteți folosi macrodefinițiile [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/kdev_t.h#L9|MAJOR]] și [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/kdev_t.h#L9|MINOR]] pentru aflarea majorului și minorului. Aceste funcții primesc ca argument câmpul ''dev'' al structurii ''struct cdev''. Câmpul de tipul ''struct cdev'' îl găsiți în structura de tipul ''struct my_device_data''. Pentru a obține structura de tipul ''struct my_device_data'', atunci când știți adresa unei variabile de tipul ''struct device'', puteți folosi funcția [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L915|dev_get_drvdata]]. | ||
- | |||
- | Țineți cont să adăugați/eliminați atributul la inițializarea/dezactivarea modulului cu ajutorul funcțiilor [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/core.c#L587|device_create_file]], [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/core.c#L611|device_remove_file]]. | ||
- | |||
- | Parcurgeți secțiunile [[:so2:laboratoare:lab12#magistrale|Magistrale]] și [[:so2:laboratoare:lab12#dispozitive|Dispozitive]] din laborator. | ||
- | </note> | ||
- | |||
- | Pentru testare rulați comanda: | ||
<code> | <code> | ||
- | # cat /sys/devices/virtualbus0/echo/myattr | + | $ echo "name type 1" > /sys/bus/bex/add |
+ | $ echo "name" > /sys/bus/bex/del | ||
</code> | </code> | ||
- | Această comanda va conduce la rularea funcției ''my_show''. | + | </note> |
- | ===== [4p] Plug and Play ===== | + | ==== 4. [2p] Înregistrarea driver-ului bex misc ==== |
- | ==== 4. [2p] Conectarea la magistrala PNP ==== | + | Modificați fișierul ''bex-misc.c'' pentru a înregistra driver-ul la magistrala ''bex''. |
+ | Inserați modulul bex_misc.ko și creați un nou device de tip ''bex'' din ''sysfs'', cu numele //Test//, tipul //misc// și versiunea //2//. Urmăriți comentariile marcate cu ''TODO 4''. | ||
- | Intrați în directorul ''parallel'', unde găsiți implementarea unui driver simplu pentru portul paralel. | + | Verificați dacă noul driver este vizibil în ''/sys/bus/bex/drivers''. |
- | Analizați conținutul fișierului ''parallel.c''. Modificați sursa astfel încât să respecte modelul ''Linux Device Model'' și ''plug and play''. Dispozitivul se va conecta la magistrala ''PNP''. | + | De ce nu este apelată funcția ''probe''? |
<note tip> | <note tip> | ||
- | Înregistrați/deînregistrați structura [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/pnp.h#L380|pnp_driver]] la încărcarea/descărcarea modulului cu ajutorul funcțiilor [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/pnp/driver.c#L266|pnp_register_driver]], respectiv [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/pnp/driver.c#L274|pnp_unregister_driver]]. | + | Observați faptul că funcția de ''match'' pentru magistrală nu este implementată în ''bex.c''. |
+ | </note> | ||
- | Pentru a fi un driver ''plug and play'', inițializarea dispozitivelor trebuie făcută în momentul în care acestea apar în sistem (la execuția funcției ''parallel_pnp_probe''), iar deînregistrarea în momentul în care dispar din sistem (la execuția funcției ''parallel_pnp_remove''). | + | Implementați funcția pentru match în fișierul ''bex.c''. Urmăriți comentariile marcate cu ''TODO 5''. |
+ | Încercați din nou adăugarea unui dispozitiv de tip ''bex'' și observați că de data aceasta funcția de ''probe'' este apelată. | ||
- | Recitiți secțiunile [[:so2:laboratoare:lab12#magistrala_pnp|Magistrala PNP]] și [[:so2:laboratoare:lab12#operatii_pnp|Operații plug and play]] din laborator. | + | ==== 5. [1.5p] Înregistrarea unui device bex misc în funcția probe ==== |
- | </note> | + | |
+ | Modificați ''bex_misc.c'' astfel încât operația ''probe'' să eșueze dacă ''version > 1''. Înregistrați device-ul misc în funcția ''bex_misc_probe()'' și deînregistrați-l în ''bex_misc_remove''. Urmăriți comentariile marcate cu ''TODO 6''. | ||
<note tip> | <note tip> | ||
- | Pentru înregistrarea și deînregistrarea unui dispozitiv folosiți funcțiile ''register_parallel_dev'' respectiv ''unregister_parallel_dev'' definite în cadrul scheletului de cod de laborator. | + | Folosiți ''misc_register()'' and ''misc_deregister()''. |
</note> | </note> | ||
- | Pentru verificare, urmăriți conținutul din directorul aferent din sysfs: | + | Creați un device nou cu numele //test//, tipul //misc// și versiunea //2// și verificați că operația ''probe'' eșuează. |
- | <code> | + | Creați un nou device cu numele //test//, tipul //misc// și versiunea //1// și verificați că operația se termină cu succes. |
- | # ls /sys/bus/pnp/drivers/parallel | + | |
- | </code> | + | |
- | ==== 5. [2p] Clase ==== | + | Verificați conținutul fișierului ''/sys/bus/bex/devices/test'' și observați că există o nouă intrare. Identificați majorul și minorul pentru device-ul ''misc'', creați un device node de tip caracter pentru acest dispozitiv (''Hint'': mknod) și încercați operații de citire și scriere pe fișierul creat, pentru a accesa buffer-ul dispozitivului. |
- | + | ||
- | Pornind de la modulul anterior, adăugați informațiile pentru o nouă clasă ''parclass'', de care aparține modulul ''paralel''. | + | |
<note tip> | <note tip> | ||
- | Definiți o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L388|class]] și o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|device]]. | + | Indicatorii ''major'' și ''minor'' sunt vizibili în atributul ''dev'' al dispozitivului de tip ''misc''. |
- | + | ||
- | Structura [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L388|class]] trebuie inițializată odată cu resursele driver-ului (la execuția funcției ''parallel_init'') și eliminată la ieșirea driverului (''parallel_exit''). Va trebui să folosiţi funcţiile [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L424|class_register]] şi [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/class.c#L212|class_unregister]]. | + | |
- | + | ||
- | În plus, pentru fiecare dispozitiv trebuie inițializată o structură [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|device]] și înregistrată cu [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/core.c#L1798|device_create]] (la execuția funcției ''parallel_pnp_probe''). La apelul funcţiei [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/core.c#L1798|device_create]], folosiți pentru al patrulea parametru construcția ''%%&dev->dev%%''. Este câmpul de tipul [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/device.h#L782|struct device]] al structurii [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/pnp.h#L244|struct pnp_dev]]. | + | |
- | + | ||
- | La înlăturarea dispozitivului (în funcţia ''parallel_pnp_remove'') folosiți funcția [[http://elixir.free-electrons.com/linux/v4.9/source/drivers/base/core.c#L1870|device_destroy]]. | + | |
- | + | ||
- | Recitiți secțiunea [[:so2:laboratoare:lab12#clase|Clase]] din laborator. | + | |
- | + | ||
</note> | </note> | ||
- | Pentru verificare, urmăriți conținutul directorului aferent din sysfs:<code> | + | ==== 6. [1p] Monitorizarea notificărilor uevent ==== |
- | # ls /sys/class/parclass/ | + | Folosiți comanda ''udevadm'' și observați ce se întâmplă când: |
- | </code> | + | * modulele ''bex.ko'' and ''bex_misc.ko'' sunt inserate |
- | ===== Extra ===== | + | * un nou device cu tipul //test// este creat |
- | == (+3 karma) USB Hotplug == | + | * un nou device cu tipul //misc// și versiunea //2// este creat |
- | + | * un nou device cu tipul //misc// și versiunea //1// este creat | |
- | În subdirectorul ''usb_extra'' găsiți o implementare minimală a unui driver USB. Analizați sursa ''usb.c'' și observați implementarea mecanismului de ''Hotplug'' si conectarea la magistrala ''USB''. Observați asemănările cu interfața dintre magistralei ''PNP'' studiată în laborator și driverele asociate: ''struct usb_driver'' / ''struct pnp_driver'', implementarea funcției ''probe'' (''skel_probe''), tabela ''skel_table'' cu care se inițializează câmpul ''id_table'' pentru a identifica device-urile compatibile, etc. | + | * toate de mai sus sunt eliminate |
- | + | ||
- | Conectați un device USB pe mașina fizică. Apelați ''dmesg'' sau ''lsusb'' pentru a identifica vendorId-ul și productId-ul device-ul atașat. | + | |
- | + | ||
- | <code bash> | + | |
- | usb 3-2: New USB device found, idVendor=1e3d, idProduct=6025 | + | |
- | </code> | + | |
- | + | ||
- | Modificați codul din ''usb.c'' pentru a crea un driver compatibil cu device-ul vostru. Compilați modulul și inserați-l pe mașina fizică (sau pe o mașină virtuală cu udev și acces la USB-ul gazdei). Reconectați device-ul USB. Ce observați la rularea comenzii dmesg? | + | |
- | + | ||
- | Cel mai probabil device-ul va fi preluat de alt driver usb din sistem (e.x. usb_storage). În acest caz, puteți descărca temporar modulul concurent (rmmod usb_storage). Dacă device-ul se conectează la driverului ''usb.ko'', puteți observa mesajul "USB Skeleton device now attached to USBSkel-0", mesaj afișat de funcția ''skel_probe''. | + | |
- | + | ||
- | Descărcați modulul. Creați o regulă ''udev'', care la identificarea dispozitivului (după ''ATTRS{idVendor}'' și ''ATTRS{idProduct}''), să încarce driverul ''usb.ko''. Recitiți secțiunea [[:so2:laboratoare:lab12#hotplug | Hotplug]] din laborator. Cu modulul descărcat, reconectați device-ul USB. Ce observați la rularea comenzilor ''dmesg'' și ''lsmod''? | + | |
- | ===== Soluții ===== | ||
- | * [[http://elf.cs.pub.ro/so2/res/laboratoare/lab12-sol.zip|Soluții exerciții laborator 12]] |