Avatar billede xited Praktikant
21. januar 2012 - 11:49 Der er 17 kommentarer og
1 løsning

Hjælp til libusb_interrupt_transfer (debian)

Jeg forsøger at rette noget kode, så det understøtter min USB vægt.
Jeg har taget udgangspunkt i https://github.com/erjiang/usbscale
Vægten er en Dymo M10

Koden registrerer at der er en vægt, men giver fejlen:
libusb:error [submit_bulk_transfer] submiturb failed error -1 errno=22

Jeg har afgrænset problemet, til denne kodestump:

        r = libusb_interrupt_transfer(
            handle,
            LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS,
            data,
            WEIGH_REPORT_SIZE, // length of data
            &len,
            10000 //timeout => 10 sec
            );

Umiddelbart gætter jeg at r burde være 0 (som er succes-retur-værdi for andre libusb funktioner) men:

r = -1

Værdierne af variablerne, er som følger:

LIBUSB_ENDPOINT_IN = 128
LIBUSB_REQUEST_TYPE_CLASS = 32
WEIGH_REPORT_SIZE = 0x06

Jeg har aldrig brugt libusb-funktioner før, så jeg er lidt på bar bund.
Hvor kommer værdierne 128 og 32 fra?

Vægten sender tilsyneladende data over usb konstant.
Jeg kan få fat på hexkoden direkte, ved at køre denne funktion:

# hexdump -v -e '6/1 "%02x " "\n"' < /dev/hidraw4

03 02 0b ff 00 00
03 04 02 00 0a 01
03 04 02 00 38 08
03 04 02 00 f8 0a
03 04 02 00 d6 01
03 04 02 00 2a 0e
03 04 02 00 38 18

...i dette eksempel trykker jeg hårdere og hårdere på vægten.
De enkelte bytes passer med brugen i koden.
De 2 sidste bytes er vægten. (eks. sidste linjes "38 18" - konverterer man "1838" til et tal, får man "6200" som var vægten der stod, da jeg trykkede hårdest.

Jeg vil dog helst bruge libusb, til at trække dataene ud.
Nogen der kan hjælpe med det?
Avatar billede segmose Nybegynder
23. januar 2012 - 10:25 #1
Det ser jo ud til at du gør det rigtig, men check lige retur koden mod dem der er angivet her:
http://libusb.sourceforge.net/api-1.0/group__syncio.html

endpoint er en slags magi, du skal vide hvad den er før du kan tale med den!

Du kan muligvis se endpoints med lsusb -v

I linket du gav med bruger de
[code]
        r = libusb_interrupt_transfer(
            handle,
            //bmRequestType => direction: in, type: class,
                    // recipient: interface
            LIBUSB_ENDPOINT_IN | //LIBUSB_REQUEST_TYPE_CLASS |
                LIBUSB_RECIPIENT_INTERFACE,
            data,
            WEIGH_REPORT_SIZE, // length of data
            &len,
            10000 //timeout => 10 sec
            );
[/code]

LIBUSB_RECIPIENT_INTERFACE istedet for LIBUSB_REQUEST_TYPE_CLASS måske er det løsningen, men igen fejlmelding skal lige fortolkes for at kunne komme videre.
Avatar billede xited Praktikant
23. januar 2012 - 19:48 #2
Jeg har prøvet alle kombinationer af de 3 variabler, tror jeg.

Angående returkoden, så er r -1.

Det er måske mig der er dårlig til C (meget muligt) men kan r være en int, og samtidig indeholde en streng?

Linje 92: int r; // holds return codes

Linje 136-144:

    if(r < 0) {
        if(r == LIBUSB_ERROR_ACCESS) {
            fprintf(stderr, "Permission denied to scale.\n");
        }
        else if(r == LIBUSB_ERROR_NO_DEVICE) {
            fprintf(stderr, "Scale has been disconnected.\n");
        }
        return -1;
    }

Er en streng mindre end 0, eller indeholder r på en eller anden måde både -1 og en tilhørende streng? (det virker underligt)
Avatar billede segmose Nybegynder
24. januar 2012 - 08:58 #3
Sæt errno = 0 før og check værdien lige (før andre kald) efter, brug evt. strerror til at fortolke værdien.

Jeg har set nogle eksempler hvor de bruger 0x81 for endpoint.

prøv at poste en
lsusb -v
den skulle kunne give oplysninger om endpoints.
Avatar billede xited Praktikant
24. januar 2012 - 11:08 #4
lsusb, for vægten:

Bus 002 Device 003: ID 0922:8006 Dymo-CoStar Corp.
Device Descriptor:
  bLength                18
  bDescriptorType        1
  bcdUSB              2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass        0
  bDeviceProtocol        0
  bMaxPacketSize0        8
  idVendor          0x0922 Dymo-CoStar Corp.
  idProduct          0x8006
  bcdDevice            1.00
  iManufacturer          1 DYMO
  iProduct                2 M10 10 Kg Digital Postal Scale
  iSerial                3 0000000001098
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                9
    bDescriptorType        2
    wTotalLength          34
    bNumInterfaces          1
    bConfigurationValue    1
    iConfiguration          0
    bmAttributes        0x80
      (Bus Powered)
    MaxPower              64mA
    Interface Descriptor:
      bLength                9
      bDescriptorType        4
      bInterfaceNumber        0
      bAlternateSetting      0
      bNumEndpoints          1
      bInterfaceClass        3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0
        HID Device Descriptor:
          bLength                9
          bDescriptorType        33
          bcdHID              1.01
          bCountryCode            0 Not supported
          bNumDescriptors        1
          bDescriptorType        34 Report
          wDescriptorLength    221
          Report Descriptor: (length is 221)
            Item(Global): Usage Page, data= [ 0x8d ] 141
                            Scale Page (POS)
            Item(Local ): Usage, data= [ 0x20 ] 32
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Local ): Usage, data= [ 0x30 ] 48
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Logical Minimum, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x27 ] 39
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Logical Maximum, data= [ 0x0a ] 10
            Item(Local ): Usage Minimum, data= [ 0x21 ] 33
                            (null)
            Item(Local ): Usage Maximum, data= [ 0x2a ] 42
                            (null)
            Item(Main  ): Feature, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x50 ] 80
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Logical Maximum, data= [ 0x0c ] 12
            Item(Local ): Usage Minimum, data= [ 0x51 ] 81
                            (null)
            Item(Local ): Usage Maximum, data= [ 0x5c ] 92
                            (null)
            Item(Main  ): Feature, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x31 ] 49
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x02 ] 2
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x81 ] 129
                            (null)
            Item(Local ): Usage, data= [ 0x80 ] 128
                            (null)
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x06 ] 6
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x32 ] 50
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x03 ] 3
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Logical Minimum, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x70 ] 112
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Logical Maximum, data= [ 0x08 ] 8
            Item(Local ): Usage Minimum, data= [ 0x71 ] 113
                            (null)
            Item(Local ): Usage Maximum, data= [ 0x78 ] 120
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x50 ] 80
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Logical Maximum, data= [ 0x0c ] 12
            Item(Local ): Usage Minimum, data= [ 0x51 ] 81
                            (null)
            Item(Local ): Usage Maximum, data= [ 0x5c ] 92
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Logical Minimum, data= [ 0x81 ] 129
            Item(Global): Logical Maximum, data= [ 0x7f ] 127
            Item(Local ): Usage, data= [ 0x41 ] 65
                            (null)
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x10 ] 16
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0xff 0x00 0x00 ] 65535
            Item(Local ): Usage, data= [ 0x40 ] 64
                            (null)
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x34 ] 52
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x05 ] 5
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x50 ] 80
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Logical Minimum, data= [ 0x01 ] 1
            Item(Global): Logical Maximum, data= [ 0x0c ] 12
            Item(Local ): Usage Minimum, data= [ 0x51 ] 81
                            (null)
            Item(Local ): Usage Maximum, data= [ 0x5c ] 92
                            (null)
            Item(Main  ): Feature, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Logical Minimum, data= [ 0x81 ] 129
            Item(Global): Logical Maximum, data= [ 0x7f ] 127
            Item(Local ): Usage, data= [ 0x41 ] 65
                            (null)
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x10 ] 16
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0xff 0x00 0x00 ] 65535
            Item(Local ): Usage, data= [ 0x40 ] 64
                            (null)
            Item(Main  ): Feature, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x35 ] 53
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x06 ] 6
            Item(Global): Report Size, data= [ 0x10 ] 16
            Item(Global): Report Count, data= [ 0x02 ] 2
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0xff 0x00 0x00 ] 65535
            Item(Local ): Usage, data= [ 0x60 ] 96
                            (null)
            Item(Local ): Usage, data= [ 0x61 ] 97
                            (null)
            Item(Main  ): Feature, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x30 ] 48
                            (null)
            Item(Main  ): Collection, data= [ 0x02 ] 2
                            Logical
            Item(Global): Report ID, data= [ 0x07 ] 7
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x0f ] 15
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x7f ] 127
            Item(Local ): Usage, data= [ 0x40 ] 64
                            (null)
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                7
        bDescriptorType        5
        bEndpointAddress    0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type              None
          Usage Type              Data
        wMaxPacketSize    0x0008  1x 8 bytes
        bInterval            200
Device Status:    0x0000
  (Bus Powered)
Avatar billede xited Praktikant
24. januar 2012 - 11:10 #5
Forsøg med errno:

#include <errno.h>

    errno = 0;
        r = libusb_interrupt_transfer(
            handle,
            //bmRequestType => direction: in, type: class,
                    //    recipient: interface
            LIBUSB_ENDPOINT_IN | //LIBUSB_REQUEST_TYPE_CLASS |
                LIBUSB_RECIPIENT_INTERFACE,
            data,
            WEIGH_REPORT_SIZE, // length of data
            &len,
            10000 //timeout => 10 sec
            );
   
            perror( "Error in USB transfer" );
            printf( "Error in USB transfer: %s\n", strerror( errno ) );

Output, når det afvikles:

Error in USB transfer: No such file or directory
Error in USB transfer: No such file or directory

Det virker forkert?
Avatar billede xited Praktikant
24. januar 2012 - 11:12 #6
Jeg har forresten smidt hele lsusb og koden, her:

http://elektronik-lavpris.dk/lsusb
http://elektronik-lavpris.dk/usbscale
Avatar billede xited Praktikant
24. januar 2012 - 11:20 #7
Og der var jeg lidt for hurtig.

Jeg har netop prøvet med følgende:

        r = libusb_interrupt_transfer(
            handle,
            //bmRequestType => direction: in, type: class,
                    //    recipient: interface
            0x82,
            data,
            WEIGH_REPORT_SIZE, // length of data
            &len,
            10000 //timeout => 10 sec
            );

...og det virker :)

Tak for hjælpen!

Smider du et svar?
Avatar billede segmose Nybegynder
24. januar 2012 - 11:49 #8
Held og lykke med projektet, det lyder meget spændende.
Avatar billede xited Praktikant
24. januar 2012 - 12:22 #10
Hmm,

Der går et eller andet galt, mellem 2 af funktionerne.

Vægten står på 1164g

data[4] = "8c"
data[5] = "04"

dat[4] + (dat[5] << 8) = 1164

I main:

if(r == 0) {
#ifdef DEBUG
            int i;
            for(i = 0; i < WEIGH_REPORT_SIZE; i++) {
                printf("%x\n", data[i]);
            }
#endif
            scale_result = print_scale_data(data);
            if(scale_result != 1)
                break;
}

I print_scale_data: (hvor jeg har indsat samme debug, som i main)

static int print_scale_data(char* dat) {

#ifdef DEBUG
            int i;
            for(i = 0; i < WEIGH_REPORT_SIZE; i++) {
                printf("%x\n", dat[i]);
            }
#endif

    uint8_t report = dat[0];
    uint8_t status = dat[1];
    uint8_t unit  = dat[2];
    uint8_t expt  = dat[3];
    double weight = (double)(dat[4] + (dat[5] << 8)) / 10;

Her bliver dat[4] = "ffffff8c" (og ikke blot "8c" som den skulle)

Hvad skyldes det mon?
Er char* ikke den korrekte type til dat?

Alle de andre værdier er uproblematiske, da de alle er under 10, og derfor antager en "alm" værdi.
Avatar billede DjJohn Nybegynder
24. januar 2012 - 12:39 #11
Vil i ikke svare på et spørgeskema som jeg skal bruge til mit projekt. Tak :-))
http://www.surveymonkey.com/s/BMBJCNG
Avatar billede segmose Nybegynder
24. januar 2012 - 12:52 #12
int     libusb_interrupt_transfer (struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);

unsigned char *

ffffff ser du kun hvis du konverterer til int/long (32-bit)
Avatar billede xited Praktikant
24. januar 2012 - 13:25 #13
Men hvor sker den konvertering?
Så vidt jeg kan se, indlæses dat jo netop som en char* ?
Avatar billede xited Praktikant
24. januar 2012 - 13:40 #14
DjJohn > Jeg tror du har mere held med deltagelse, hvis du opretter en tråd under diverse, eller lignende.
Avatar billede segmose Nybegynder
24. januar 2012 - 14:03 #15
Type konvertering under C/C++ er meget interessant.

Når du har en signed char 0x8c og konverterer den til signed int (32 bit) så ser int'en den højeste bit som fortegns bit og så får du din it til at se sådan ud, da 0x8c som signed er et negativt tal og så fortegns bitten forlænges til 0xffffff8c, hvis du vil vide mere så skal du læse om 1's komplement.

Hvis du deler din
double weight = (double)(dat[4] + (dat[5] << 8)) / 10;
lidt op så kan du bedre se det.

Du kan
    signed char dat[8]; // prøv bagefter med unsigned
    dat[4] = 0x8c;
    int tal = dat[4];
Avatar billede xited Praktikant
24. januar 2012 - 14:30 #16
O.k. så blev jeg *lidt* klogere.
Men libusb_interrupt_transfer returnerer unsigned, ser det ud til?
Hvordan konverterer jeg det?
Avatar billede xited Praktikant
24. januar 2012 - 14:37 #17
unsigned char* dat = data_signed;

:S

Well, det ser ud til at virke.
Jeg har aldrig været en ørn til datatyper.

Tak for hjælpen!
Avatar billede segmose Nybegynder
24. januar 2012 - 16:34 #18
Den vil faktisk have "unsigned char *"


int    libusb_interrupt_transfer (struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester