IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

[Linux] Lecture périphérique USB HID [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 15
    Points : 13
    Points
    13
    Par défaut [Linux] Lecture périphérique USB HID
    Bonjour,

    Je cherche a lire sur un peripherique usb HID avec la libhid sous linux (ubuntu 10.04).
    http://libhid.alioth.debian.org/

    Le peripherique est fonctionnel et les droits correctement configurés car j'y accede sans probleme avec un programme en C et un autre en Purebasic.

    Le code fpc/lazarus utilisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
     program project1;
     
      {$mode objfpc}{$H+}
     
      uses
        {$IFDEF UNIX}{$IFDEF UseCThreads}
        cthreads,
        {$ENDIF}{$ENDIF}
        Classes,dynlibs,sysutils;
     
     
      {$R *.res}
     
      Type
     
      hid_return_t = (HID_RET_SUCCESS := 0,HID_RET_INVALID_PARAMETER,
         HID_RET_NOT_INITIALISED,HID_RET_ALREADY_INITIALISED,
         HID_RET_FAIL_FIND_BUSSES,HID_RET_FAIL_FIND_DEVICES,
         HID_RET_FAIL_OPEN_DEVICE,HID_RET_DEVICE_NOT_FOUND,
         HID_RET_DEVICE_NOT_OPENED,HID_RET_DEVICE_ALREADY_OPENED,
         HID_RET_FAIL_CLOSE_DEVICE,HID_RET_FAIL_CLAIM_IFACE,
         HID_RET_FAIL_DETACH_DRIVER,HID_RET_NOT_HID_DEVICE,
         HID_RET_HID_DESC_SHORT,HID_RET_REPORT_DESC_SHORT,
         HID_RET_REPORT_DESC_LONG,HID_RET_FAIL_ALLOC,
         HID_RET_OUT_OF_SPACE,HID_RET_FAIL_SET_REPORT,
         HID_RET_FAIL_GET_REPORT,HID_RET_FAIL_INT_READ,
         HID_RET_NOT_FOUND);
     
     
     
      THIDInterfaceMatcher = record
         vendor_id : word;
         product_id :word;
         matcher_fn : pointer;
         custom_data : pointer;
         custom_data_length :word;
      end;
      HIDInterfaceMatcher = THIDInterfaceMatcher;
      PHIDInterfaceMatcher = ^HIDInterfaceMatcher;
     
      THidInit=function : hid_return_t ;
      THidNewInterface=function : pointer;
      THidForceOpen=function (hidif:pointer; iface:longint; matcher:PHIDInterfaceMatcher; retries:word):hid_return_t;
     
      var
        Hlib:TLibHandle;
        HidInit:THidInit;
        HidNewInterface:THidNewInterface;
        HidForceOpen:THidForceOpen;
     
        NewIface:pointer;
        IMU:THIDInterfaceMatcher;
        PIMU:PHIDInterfaceMatcher;
      begin
     
     
      Hlib:=loadlibrary('libhid.so');
      if Hlib<>nilhandle then writeln('Chargement lib OK');
      HidInit := THidInit(GetProcAddress(Hlib, 'hid_init'));
      HidNewInterface := THidNewInterface(GetProcAddress(Hlib, 'hid_new_HIDInterface'));
      HidForceOpen := THidForceOpen(GetProcAddress(Hlib, 'hid_force_open'));
     
     
      If HidInit()=HID_RET_SUCCESS then writeln('Init OK');
      NewIface:=HidNewInterface();
     
      IMU.vendor_id:=$20FF;
      IMU.product_id:=$0100;
      IMU.matcher_fn:=nil;
      IMU.custom_data:=nil;
      IMU.custom_data_length:=0;
     
     
      HidForceOpen(NewIface,1,@PIMU,3);
      if HidForceOpen(NewIface,0,@IMU,3) = HID_RET_SUCCESS then writeln('Ouverture OK');
     
      end.
    J'obtiens cette erreur

    An unhandled exception occurred at $00E47C3E :
    EAccessViolation : Access violation
    $00E47C3E
    $00E48EA6
    $0804837F
    a la ligne ==> HidForceOpen(NewIface,1,@PIMU,3);
    Le probleme semble venir du pointer NewIface.
    Si je declare un int64 au lieu d'un type pointer plus d'erreur mais l'interface n'est pas ouverte.

    En C j'utilise ce code qui fonctionne sans souci :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    //gcc -Wall -W -L/usr/lib/ -lhid hid.c -o hid
    #include <hid.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
     
     
    unsigned char INDATA[100];
    int i;
    double x;
     
    int main(void)
    {
      HIDInterface* hid;
      hid_return ret;
      HIDInterfaceMatcher matcher = { 0x20ff, 0x0100, NULL, NULL, 0 };
     
     
    ret = hid_init();
    if (ret != HID_RET_SUCCESS) {
    printf("Erreur Init HID \n");
    return -1;
    }
    else
    {
    printf("Init HID OK\n");
    }	
     
    hid = hid_new_HIDInterface();
    if (hid == 0) {
    printf("Erreur ouverture Interface\n"); 
    return -1; 
    }
    else
    {
    printf("ouverture Interface OK\n");  
    }
     
    ret = hid_force_open(hid, 1, &matcher, 3);
    printf("%d\n",ret);
    ret = hid_force_open(hid, 0, &matcher, 3);
     
    if (ret == HID_RET_SUCCESS) {
    printf("IMU Ouverte\n"); 
    }
    else
    {
    printf("Erreur Ouverture IMU\n");
    return -1;
    }
     
     
    ret=hid_interrupt_read(hid,0x82,INDATA,15,0);
    if (ret == HID_RET_SUCCESS) {
    printf("Lecture IMU OK\n"); 
    }
    else
    {
    printf("Erreur Lecture IMU\n");
    return -1;
    }
     
     
    x = ((INDATA[4]|(INDATA[5]<<8))-32768)*0.000183105469;
     
    printf (" valeur ==> %f\n",x);
     
    return 0;
    }


    et en Purebasic ceci
    Code VB : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    ImportC "/usr/lib/libhid.so"
      hid_init()
      hid_cleanup()
      hid_new_HIDInterface()
      hid_force_open (HIDInterface, iface,HIDInterfaceMatcher,Retries)
      hid_interrupt_read(HIDinterface,Adr,buf,len,f)
      hid_close(HIDInterface)
    EndImport
     
     
    #HID_RET_SUCCESS =0	
    #HID_RET_INVALID_PARAMETER 	=1
    #HID_RET_NOT_INITIALISED 	=2
    #HID_RET_ALREADY_INITIALISED=3 	
    #HID_RET_FAIL_FIND_BUSSES 	=4
    #HID_RET_FAIL_FIND_DEVICES 	=5
    #HID_RET_FAIL_OPEN_DEVICE 	=6
    #HID_RET_DEVICE_NOT_FOUND 	=7
    #HID_RET_DEVICE_NOT_OPENED 	=8
    #HID_RET_DEVICE_ALREADY_OPENED =9	
    #HID_RET_FAIL_CLOSE_DEVICE =10
    #HID_RET_FAIL_CLAIM_IFACE 	=11
    #HID_RET_FAIL_DETACH_DRIVER 	=12
    #HID_RET_NOT_HID_DEVICE 	=13
    #HID_RET_HID_DESC_SHORT 	=14
    #HID_RET_REPORT_DESC_SHORT 	=15
    #HID_RET_REPORT_DESC_LONG 	=16
    #HID_RET_FAIL_ALLOC 	=17
    #HID_RET_OUT_OF_SPACE 	=18
    #HID_RET_FAIL_SET_REPORT 	=19
    #HID_RET_FAIL_GET_REPORT 	=20
    #HID_RET_FAIL_INT_READ 	=21
    #HID_RET_NOT_FOUND 	=22
    #HID_RET_TIMEOUT 	=23
     
     
    Structure THIDInterfaceMatcher
      vendor_id.u
      product_id.u
      custom_matcher.l
      custom_data.l
      lon.q
    EndStructure
     
    Dim Indata.c(20)
     
    If hid_init()=#HID_RET_SUCCESS
     
      *h=hid_new_HIDInterface()
     
      If *h
        Hid_force_open(*h,1,@Matcher,3)
        If hid_force_open(*h,0,@Matcher,3)=#HID_RET_SUCCESS
          If hid_interrupt_read(*h,$82,@InData(),15,0)=#HID_RET_SUCCESS
            For X=0 To 14 
              Debug InData(X)
            Next x
          EndIf
        EndIf
      EndIf
    EndIf

    Ci j'utilise en fpc les mêmes types de variable qu' en purebasic j'ai droit a un :
    Access violation
    Avez vous une idée

    Merci

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Points : 506
    Points
    506
    Par défaut
    1- Les fonctions (et procédure) n'ont pas les mêmes conventions d'appel en C et en Pascal. Il faut donc dire à ton compilateur Pascal que tes fonctions venant du C ont la convention d'appel C avec cdecl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    THidInit=function : hid_return_t ; cdecl;
    THidNewInterface=function : pointer; cdecl;
    THidForceOpen=function (hidif:pointer; iface:longint; matcher:PHIDInterfaceMatcher; retries:word):hid_return_t; cdecl;

    2 - Pas besoin de sortir l'artillerie lourde (LoadLibrary, GetProcAddress) pour lier du C et du Pascal : ftp://ftp.freepascal.org/pub/fpc/doc...FreePascal.pdf

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Merci,

    Cela fonctionne parfaitement avec cdecl.

    Je vais etudier ton pdf a tête reposée.

    Bonne fin de journée

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Re bonjour

    Je poursuis dans ce topic car j'essaie de faire la même chose sous windows maintenant que tout fonctionne sous linux.

    Au lieu d'utiliser la libhid j'utilise une dll fournie par le constructeur du materiel.

    Comme avec la version linux, avant de poster j'ai fait des tests en C et en PureBasic et cela fonctionne parfaitement.

    Sous Lazarus c'est un peu plus chaud.
    En fait je peux acceder exactement 36 fois a la dll puis j'ai droit a un SIGSEGV

    Le code que j'utilise

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    {$ifdef win32}
    type
     
     TIndata=array[0..15] of byte;
     Indata=TIndata;
     PIndata=^Indata;
     
     
     THidSetInterface=procedure(I:integer); cdecl;
     THidOpen=function(Vid,Pid:word;Manuf,Serial,Device:pointer;Sync:longint):longint; cdecl;
      THidRead=function(BufData:PIndata):longint;cdecl;
     
    var
      Hlib:TlibHandle;
      HidSetInterface:THidSetInterface;
      HidOpen:THidOpen;
      HidRead:THidRead;
      Pbuf:PinData;
      RawAxes:Array[0..7] of integer;
      Buttons:array[0..1] of integer;
      ByteIndex:integer;
    begin
     
     
      Hlib:=loadlibrary('UsbHidApi.dll');
      HidSetInterface := THidSetInterface(GetProcAddress(Hlib, 'SetInterface'));
      HidOpen:=THidOpen(GetProcAddress(Hlib,'Open'));
      HidRead:=THidRead(GetProcAddress(Hlib,'Read'));
      HidSetInterface(1);
      r:=HidOpen(8447,256,nil,nil,nil,1);
     
     
       New(Pbuf);
       r:=HidRead(Pbuf);
     
       if r>0 then
       begin
       ByteIndex:=1;
       For i := 0 To 6 do
       Begin
       RawAxes[i] := Pbuf^[ByteIndex] + 256*Pbuf^[ByteIndex+1];
       ByteIndex:=ByteIndex+2;
       end;
     
     
       Buttons[0] := Pbuf^[ByteIndex] and 1;
       Buttons[1] := (Pbuf^[ByteIndex] div 2) and 1;
       RawAxes[7] := (Pbuf^[ByteIndex]>>4)and $f;
     
     
       Dispose(Pbuf);
     
    .................................
    ........................
    Dans la datasheet du constructeur la dll est docummentée comme ceci pour les 3 fonctions utilisées

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int Read(void *pBuf);
    void SetInterface (int iface);
    int Open (unsigned int VendorID,unsigned int ProductID,char *Manufacturer,char *SerialNum,char *DeviceName,int bAsync);

    le code C fourni :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    const int DATALEN = 15;
    int interfaceid = 0;
    int Nbytes = 0;
    int VID = 0x20ff;
    int PID = 0x0100;
    unsigned char indata[DATALEN];
     
    SetInterface(1);
    if(connected = Open(VID,PID,NULL,NULL,NULL,1)){
    while(connected){
    if(Nbytes = Read(indata)>0){
    displayindata(indata,Nbytes);
    }
    }
    }

    Il y a quelque chose qui m'echappe mais je ne vois vraiment pas quoi

    Une idée ?

    Merci

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Ce coup ci il faut remplacer cdecl par stdcall et tout fonctionne

    A+

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    j'ai analysé ton code concernant le chargement de la librairie libhid.so en faite je ne comprends pas a quoi corresponds cette partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     HidForceOpen(NewIface,1,@PIMU,3);
      if HidForceOpen(NewIface,0,@IMU,3) = HID_RET_SUCCESS then
           writeln('Ouverture OK');
    De plus tout le reste fonctionne correctement sauf cette partie la où je ne passe jamais par le writeln.

    Cordialement.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Salut

    en fait je n'aurai pas du mettre les deux lignes
    Il y a un bug dans le firmware de mon perif hid et je suis obligé de le faire planter sur l'interface 1 pour pouvoir ouvrir l'interface 0

    Donc si tu utilises l'interface 1 tu ne veras pas le writeln

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2003] Detecter et lecture périphérique USB installer sur l'ordinateur
    Par Expensive dans le forum IHM
    Réponses: 0
    Dernier message: 10/01/2013, 11h49
  2. Contrôler un périphérique USB HID avec Android
    Par GGelec dans le forum Android
    Réponses: 0
    Dernier message: 27/07/2012, 17h37
  3. USB HID, lecture impossible
    Par ivan dans le forum Linux
    Réponses: 0
    Dernier message: 09/05/2012, 17h44
  4. [WDK] Gestion des évènements liés aux périphériques USB HID
    Par Aymeric Suteau dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 28/04/2011, 14h39
  5. Détecter les périphériques USB sous linux
    Par bertigo dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 23/11/2010, 12h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo