Forum: Mikrocontroller und Digitale Elektronik libusb: LIBUSB_ERROR_BUSY


von Axel V. (axel-f)


Angehängte Dateien:

Lesenswert?

Habe mir hier ein Testboard für den STM32H743 aufgebaut. Im Moment bin 
ich bei der Inbetriebnahme des FS USB. Ich habe sowohl ein 
"CDC-Standalone" Beispiel von ST als auch ein "Custom HID" Beispiel am 
laufen. Das Gerät ist am PC (Linux) per 'lsusb' auf der Konsole 
einwandfrei zu finden.

Eine Testsoftware, die libusb verwendet und in einem früheren Projekt 
bereits funktioniert hat, liefert nach dem anstecken des H743 Boards 
immer LIBUSB_ERROR_BUSY als Konfig Fehler:
1
// Testboard_H743_cb suchen & finden
2
        usb_error= libusb_init(NULL);
3
        if(usb_error)
4
            printf("USB Fehler: %i\n", usb_error);
5
        handle_usb=libusb_open_device_with_vid_pid(NULL, STM, VID);
6
        if(handle_usb== NULL)
7
            printf("Testboard H743 nicht gefunden \n");
8
        else
9
        {
10
            printf("Testboard H743 gefunden \n");
11
            usb_error=  libusb_set_configuration(handle_usb, 1);
12
            if(usb_error)
13
            {
14
                printf("Konfig Fehler: %i\n", usb_error);
15
            }

Das Suchprogramm läuft zyklisch, anbei noch die Konsolenausgabe.
Hat jemand eine Idee, in welche Richtung ich suchen sollte?

Danke & Gruß, Axel

: Verschoben durch Moderator
von Richie (mikro123)


Lesenswert?

1
int libusb_detach_kernel_driver(libusb_device_handle *devh, int interface)
1
int libusb_set_auto_detach_kernel_driver(libusb_device_handle *devh, int enable)

von Axel V. (axel-f)


Lesenswert?

Moin Richie,
so, wie ich Deiner Antwort entnehme, gehst Du davon aus, daß der Kernel 
derzeit versucht, USB-Geräte bekannter Klassen sofort in Beschlag zu 
nehmen (claimen). Ich werde das nachher gleich testen.
Wahrscheinlich könnte ich auch eine "vendor specific class" nehmen, dann 
kann der Kernel nix claimen.
Bin selbst nicht so der Überflieger in Sachen USB, aber ich versuche 
mich gerade durchzubeißen.

Edit:
Das war es noch nicht, libusb_detach_kernel_driver() gibt zurück -5, 
also war das Gerät wohl nicht vom Kernel belegt.
Hast Du noch eine Idee?

Danke & Gruß, Axel

: Bearbeitet durch User
von J. S. (jojos)


Lesenswert?

Liefert dmesg irgendwelche Infos?

von Axel V. (axel-f)


Lesenswert?

dmesg liefert dieses:
1
[ 3023.857373] usb 5-3.2.1: new full-speed USB device number 8 using xhci_hcd
2
[ 3024.089776] usb 5-3.2.1: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
3
[ 3024.089779] usb 5-3.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
4
[ 3024.089781] usb 5-3.2.1: Product: STM32 Virtual ComPort in FS Mod
5
[ 3024.089782] usb 5-3.2.1: Manufacturer: STMicroelectronics
6
[ 3024.089783] usb 5-3.2.1: SerialNumber: 0000000C0000
7
[ 3024.141823] cdc_acm 5-3.2.1:1.0: ttyACM0: USB ACM device
8
[ 3024.396432] usb 5-3.2.1: selecting invalid altsetting 1
9
[ 3027.311353] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #1
10
[ 3027.311357] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #-1
11
[ 3027.812112] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #1
12
[ 3027.812117] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #-1
13
[ 3028.312604] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #1
14
[ 3028.312609] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #-1
15
[ 3028.813171] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #1
16
[ 3028.813176] usb 5-3.2.1: usbfs: interface 0 claimed by usbfs while 'Testboard_H743_' sets config #-1
17
[ 3028.908740] usb 5-3.2.1: USB disconnect, device number 8

(Mod: pre-Tags hinzgefügt, sonst sieht das in der Mobilansicht unlesbar 
aus.)

: Bearbeitet durch Moderator
von Harald K. (kirnbichler)


Lesenswert?

Lass' Dir mal den USB-Devicedescriptor von dem Ding ausgeben.

Was ist der Zweck von

> libusb_set_configuration(handle_usb, 1);

Axel V. schrieb:
> [ 3024.396432] usb 5-3.2.1: selecting invalid altsetting 1

Hmm.

von Thomas Z. (usbman)


Lesenswert?

Harald K. schrieb:
>> [ 3024.396432] usb 5-3.2.1: selecting invalid altsetting 1

Das ist ein SetInterface (1) request. Geht bei CDC natürlich nicht.
CDC ist ein Compound Device und hat 2 Interfaces die beide in den libusb 
Strukturen initialisiert werden müssen.

Also entweder das Devíce mit den Lowlevel Requests ansteuern oder halt 
die Deskriptoren auswerten und die Strukturen befüllen.

von Jim M. (turboj)


Lesenswert?

Axel V. schrieb:
> Das war es noch nicht, libusb_detach_kernel_driver() gibt zurück -5,
> also war das Gerät wohl nicht vom Kernel belegt.

Nö.

Der gibt -5 zurück weil Du keine Root Rechte hast.

Las das ganze mal mit sudo laufen, kernel detach privilegien hat der 
User normalerweise nicht.

Der Hint in dmesg ist übrigens:
"[ 3024.141823] cdc_acm 5-3.2.1:1.0: ttyACM0: USB ACM device"

Denn hier hat der USB CDC Treiber sich die Interfaces gegriffen (USB CDC 
ACM müsste 2 Interfaces definieren).

von Axel V. (axel-f)


Angehängte Dateien:

Lesenswert?

Anbei Devicedeskriptor.

Wahrscheinlich wäre es sinnvoll, das device auf vendor class zu stellen. 
Daher kommt die SW im ersten Beitrag. Im Endeffekt brauche ich zwei bulk 
endpoints für Ein- und Ausgabe aufs device. Nix zeitkritisches.

@usbman: bist Du auch der Meinung, das ein umstellen auf vendor-class 
sinnvoll wäre?

@turboj: auch als root kommt -5 zurück.

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Ein Versuch wäre es, ein unbind auf das Device zu machen.
Als root:
1
# cd /sys/bus/usb/drivers/cdc_acm
2
# ls -lL
3
drwxr-xr-x 5 root root    0 30. Mär 16:51 1-1.3.2:1.0
4
drwxr-xr-x 5 root root    0 30. Mär 16:51 1-1.3.2:1.1
5
Entweder:
6
# echo 1-1.3.2:1.1 > unbind
7
oder:
8
# echo 1-1.3.2:1.0 > unbind

von Thomas Z. (usbman)


Lesenswert?

Axel V. schrieb:
> Im Endeffekt brauche ich zwei bulk
> endpoints für Ein- und Ausgabe aufs device. Nix zeitkritisches.

Warum baust du ein CDC wenn du nur 2 Bulk EPs brauchst? Zumal dein CDC 
noch nicht mal spec konform ist.
Wie gesagt CDC ist ein Compount Device und braucht eigentlich zwingend 
IAD. Mir ist auch klar dass es ohne IAD geht, aber halt nicht spec 
konform. Das hast du wohl bei STM abgeschrieben.

Wenn du auf Vendor umstellst wird kein CDC mehr erkannt. Die Pipes auf 
deinem Interface 1 musst du trotzdem initialisieren. Ich bin kein Freund 
von Libusb, aber wenn ich mich richtig erinnere muss vor dem Configure 
die Pipe Struktur gefüllt werden.

Zur Not kannst du auch Vendor CTL Requests ganz ohne EPs benutzen. Der 
usbASP macht das so.

https://github.com/usbman01/CH552_usbASP/blob/main/source/src/usbdrv.c

ich erreiche damit locker 6KB/s begrenzt durch den Flashing Speed

von Axel V. (axel-f)


Lesenswert?

> Das hast du wohl bei STM abgeschrieben.
Es ist noch viel schlimmer; ich habe ein Beispiel von ST einfach 
hergenommen und kompiliert. Da ich das Board selbst aufgebaut habe, ging 
es natürlich erst mal darum, die Hardware prinzipiell in Funktion zu 
kriegen. Schnittstellen, auf denen man beide Seiten programmieren muß, 
sind halt von vornherein Henne-Ei-Problem.
Das CDC lief praktisch auf Anhieb, d.h. hat Daten vom PC direkt auf 
Ausgangs-UART vom H743 geschrieben.
Auf PC-Seite hole ich mir mit folgender Initialisierung mein Device:
1
        handle_usb=libusb_open_device_with_vid_pid(NULL, STM, VID);
2
        if(handle_usb== NULL)
3
            printf("Testboard H743 nicht gefunden \n");
4
        else
5
        {
6
            printf("Testboard H743 gefunden \n");
7
            usb_error=  libusb_set_configuration(handle_usb, 1);
8
            if(usb_error)
9
            {
10
                printf("Konfig Fehler: %i\n", usb_error);
11
                libusb_set_configuration(handle_usb, -1);
12
            }
13
            else
14
            {
15
                printf("konfiguriert...\n");
16
                usb_error=  libusb_claim_interface(handle_usb, 0);
17
                if(usb_error)
18
                    printf("Interface Fehler: %i\n", usb_error);
19
                else
20
                {
21
                    printf("Interface claimed \n");
22
                    usb_error=  libusb_set_interface_alt_setting(handle_usb, 0, 1);
23
                    if(usb_error)
24
                        printf("Alternate Fehler: %i\n", usb_error);
25
                    else
26
                    {
27
                        printf("Alternate set \n");
28
                        FH_connected= true;
29
                        gtk_label_set_attributes(statuszeile, hg_hellgrau);
30
                        gtk_label_set_text(statuszeile, "Verbunden");
31
                        programmblock_out->blocktyp= DUMMY;
32
                        libusb_bulk_transfer(handle_usb, EP_OUT, (unsigned char*)&outbuf, 500,  (int *)&transferred,20);
33
                    }
34
                }
35
            }
36
        }
Vielleicht kannst Du es kurz ansehen, ob arg Käse drin steht. Wie 
gesagt, es hat mal funktioniert, aber das heißt ja nix. Ich schaue mir 
Dein Beispiel lt. Link an.
Danke schon mal!!

von Harald K. (kirnbichler)


Lesenswert?

Axel V. schrieb:
> Das CDC lief praktisch auf Anhieb, d.h. hat Daten vom PC direkt auf
> Ausgangs-UART vom H743 geschrieben.

Na, das bedeutet, daß das Codebeispiel so schlecht nicht ist.

Das Problem wird bei Deinem Versuch liegen, mit einem CDC-Device zu 
reden.

Hier gibts ein Beispiel, wie so etwas geht:

https://github.com/tytouf/libusb-cdc-example/blob/master/cdc_example.c

Das sieht ein bisschen anders aus, meinst Du nicht auch?

von Axel V. (axel-f)


Lesenswert?

Ja klar, das sieht anders aus. So, wie ich das Beispiel verstehe, muß 
man erst mal 'irgendwem' das Interface aus den Klauen reißen. Deswegen 
werde ich meinen Code auf dem Device auf vendor class umstellen. Oder 
auf HID class. Das paßt vermutlich auch besser auf meine eigentliche 
Anforderung. Wie bereits gesagt, war das CDC nur der Versuch, das USB 
auf dem device überhaupt zum laufen zu kriegen.

Herzlichen Dank für den Tip!

von Thomas Z. (usbman)


Lesenswert?

Axel V. schrieb:
> So, wie ich das Beispiel verstehe, muß
> man erst mal 'irgendwem' das Interface aus den Klauen reißen. Deswegen
> werde ich meinen Code auf dem Device auf vendor class umstellen.

wieso denn? Beim HID hättest du das gleiche Problem...

- Lass usb_error= libusb_set_configuration(handle_usb, 1); weg
- dann libusb_detach_kernel_driver(handle_usb, 1); //Interface 1
- und  libusb_claim_interface(handle_usb, 1);//Interface 1
- und  libusb_set_interface_alt_setting(handle_usb, 1, 0); //alt 0.

alt setings kannst du auch weglassen. Wenn du das aufrufst dann halt mit 
alt 0 alternate settings gibt es nur bei ISO Transfers um die Bandbreite 
zuzuteilen.

Wichtig ist dass du immer Interface 1 angibst, das ist dein Transfer 
Interface mit den Bulk Eps. Dann sollte das auch auf deinem CDC 
marschieren.

https://libusb.sourceforge.io/api-1.0/libusb_api.html

: Bearbeitet durch User
von Axel V. (axel-f)


Lesenswert?

Ja, ich glaube, das war's. Code sieht jetzt so aus:
1
        handle_usb=libusb_open_device_with_vid_pid(NULL, STM, VID);
2
        if(handle_usb== NULL)
3
            printf("Testboard H743 nicht gefunden \n");
4
        else
5
        {
6
            printf("Testboard H743 gefunden \n");
7
            usb_error=  libusb_detach_kernel_driver(handle_usb, 1);
8
            printf("Detach Kernel: %i\n", usb_error);
9
            usb_error=  libusb_claim_interface(handle_usb, 1);
10
            printf("Claim IF: %i\n", usb_error);
11
            FH_connected= true;
12
            gtk_label_set_attributes(statuszeile, hg_hellgrau);
13
            gtk_label_set_text(statuszeile, "Verbunden");
Detach Kernel und Claim IF gibt jedes Mal 0 zurück. Danach schicke ich 
jede halbe sec. ein paar Zeichen runter und die kommen an. Jetzt kommt 
als nächstes die Empfangsrichtung...

Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.