Libusb usage

As a new user, i’m tryng to install in haiku some software i need for daily use. One of them is a software for controlling the CH341 Programmer. Under linux i use ch341eepromtool, a console mode software that make use of libusb. I saw, and installed, libusb 1.0.26 from haikudepot, and now i’m trying to compile the tool, with, as you can imagine, some “trouble”:

  1. There is no libusb.h installed, why?
  2. Trying to compile libusb from source , following the steps in the .recipe lead me to this error in the configure step:

configure: error: compiler with C11 support is required to build libusb

But obviovsly someone managed to compile it. How???

  1. Manually adding libusb.h in the source dir of ch341eepromtool, and adjusting the source, lead me to this error:

/packages/gcc-2.95.3_2023_08_05-1/.self/develop/tools/i586-pc-haiku/bin/ld: cannot find -lusb1.0
collect2: ld returned 1 exit status

The command for compile is : gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0

So it seems the linker cannot find the libusb library Any “magic” advice? Thanks

You need devel packages. As they are of no use for a lambda user, sources and devel packages are not shown in HaikuDepot, by default. You just need to go in the menu and select them.

2 Likes

Installed the dev package, now i’ve libusb.h, but still linker error.

This is the software i’m referring to GitHub - stefanct/ch341eepromtool: The EEPROM software for the WCH CH341A originally written by asbokid

With a few patches it works (errno.h + one for mutliple definition):

/Opslag/wip/ch341eepromtool> ./ch341eeprom 
ch341eeprom - an i2c EEPROM programming tool for the WCH CH341a IC
Version 0.5 copyright (c) 2011  asbokid <ballymunboy@gmail.com>

This program comes with asbolutely no warranty; This is free software,
and you are welcome to redistribute it under certain conditions:
GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html

Usage:
 -h, --help             display this text
 -v, --verbose          verbose output
 -d, --debug            debug output
 -s, --size             size of EEPROM {24c32|24c64}
 -e, --erase            erase EEPROM (fill with 0xff)
 -w, --write <filename> write EEPROM with image from filename
 -r, --read  <filename> read EEPROM and save image to filename

Example:  ch341eeprom -v -s 24c64 -w bootrom.bin

What I’ve done:

/Opslag/wip/ch341eepromtool> git diff
diff --git a/ch341eeprom.c b/ch341eeprom.c
index 61ef4c1..a3e80bf 100644
--- a/ch341eeprom.c
+++ b/ch341eeprom.c
@@ -19,7 +19,11 @@
 //   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <libusb-1.0/libusb.h> 
-#include <asm/errno.h>
+#ifdef __HAIKU__
+    #include <errno.h>
+#else
+    #include <asm/errno.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/ch341funcs.c b/ch341funcs.c
index 23c5236..c1cd1bd 100644
--- a/ch341funcs.c
+++ b/ch341funcs.c
@@ -19,7 +19,11 @@
 //   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <libusb-1.0/libusb.h>
-#include <asm/errno.h>
+#ifdef __HAIKU__
+    #include <errno.h>
+#else
+    #include <asm/errno.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -30,7 +34,7 @@ extern FILE *debugout, *verbout;
 uint32_t getnextpkt;                            // set by the callback function
 uint32_t syncackpkt;                            // synch / ack flag used by BULK OUT cb function
 uint16_t byteoffset;
-uint8_t *readbuf;
+extern uint8_t *readbuf;
 
 // --------------------------------------------------------------------------
 // ch341configure()

I too, did solved the errno.h issue, but how did you compile it? Didn’t you get the ld error?

Just used the cmd you gave earlier: **gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0**

From Terminal:

/Opslag/wip/ch341eepromtool> gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0
ch341eeprom.c:22:10: fatal error: asm/errno.h: No such file or directory
   22 | #include <asm/errno.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
ch341funcs.c:22:10: fatal error: asm/errno.h: No such file or directory
   22 | #include <asm/errno.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
/Opslag/wip/ch341eepromtool> gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0
ch341funcs.c:22:10: fatal error: asm/errno.h: No such file or directory
   22 | #include <asm/errno.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
/Opslag/wip/ch341eepromtool> gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0
ch341funcs.c: In function 'ch341configure':
ch341funcs.c:66:5: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
   66 |     libusb_set_debug(NULL, 3);                  // maximum debug logging level
      |     ^~~~~~~~~~~~~~~~
In file included from ch341funcs.c:21:
/boot/system/develop/headers/libusb-1.0/libusb.h:1365:18: note: declared here
 1365 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
/boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/13.2.0/../../../../x86_64-unknown-haiku/bin/ld: /tmp//ccY4OCyG.o:(.bss+0x10): multiple definition of `readbuf'; /tmp//ccYN8Owk.o:(.bss+0x10): first defined here
collect2: error: ld returned 1 exit status
/Opslag/wip/ch341eepromtool> gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0
ch341funcs.c: In function 'ch341configure':
ch341funcs.c:66:5: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
   66 |     libusb_set_debug(NULL, 3);                  // maximum debug logging level
      |     ^~~~~~~~~~~~~~~~
In file included from ch341funcs.c:21:
/boot/system/develop/headers/libusb-1.0/libusb.h:1365:18: note: declared here
 1365 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
/Opslag/wip/ch341eepromtool> ls
ch341eeprom  ch341eeprom.c  ch341eeprom.h  ch341funcs.c  COPYING  mktestimg.c  README.md

Uhm… Strange… so why i get this error

/packages/gcc-2.95.3_2023_08_05-1/.self/develop/tools/i586-pc-haiku/bin/ld: cannot find -lusb-1.0
collect2: ld returned 1 exit status

Do i miss some packages?

Ah! you are on 32bit :slight_smile: use “setarch x86” in Terminal, this switches from the old gcc2 compiler to the newer gcc13 compiler, that should fix the build (I guess you installed “libusb_x86_devel”?, if so you should be good)

Oooooh… so this is the magic spell
setarch x86

Is it good to make it default?

Anyway , thankyou

1 Like

How do you make x86 the default?
While allowing it to be switched back.

No luck for me with this OS… :rofl: :rofl:
At first it stops here:

Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
Found [1a86:5512] as device [2] on USB bus [0]
Opened device [1a86:5512]
Failed to detach kernel driver: 'No Error (12)'
Couldnt configure USB device

Seems it cannot detach the kernel driver (From the syslog :
KERN: usb hub 2: port 1: new device connected
KERN: usb_audio:05.45.114:init_driver::ver.0.0.5
Not shure if related)

Modifing the source from

if(libusb_kernel_driver_active(devHandle, DEFAULT_INTERFACE)) {
        ret = libusb_detach_kernel_driver(devHandle, DEFAULT_INTERFACE);
        if(ret) {
            fprintf(stderr, "Failed to detach kernel driver: '%s'\n", strerror(-ret));
            return NULL;
        } else
            fprintf(verbout, "Detached kernel driver\n");

to

if(libusb_kernel_driver_active(devHandle, DEFAULT_INTERFACE)) {
        ret = libusb_detach_kernel_driver(devHandle, DEFAULT_INTERFACE);
              fprintf(verbout, "Detached kernel driver\n");

I get this

Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
Found [1a86:5512] as device [2] on USB bus [0]
Opened device [1a86:5512]
Detached kernel driver
Claimed device interface [0]
Device reported its revision [4.03]
Configured USB device
Set i2c bus speed to [100kHz]
Read [0] of [8192] bytes      

And it stuck here. The software , i think, wait for some data from the usb.
Any advice?

That message should appear when reading from a i2c memory, when you would have passed the parameters in the command line.

Yes. If not clear, i’ve the programmer and it was connected, so i tried to read the i2c eeprom

Is there any way i can contact the lib porter?

The source hasn’t been updated since 2015, so not sure how uptodate it is (probably doesn’t make any difference).
I can’t check on a i2c eeprom, so this is what I can get around too at the moment:

~/test> ch341eeprom
ch341eeprom - an i2c EEPROM programming tool for the WCH CH341a IC
Version 0.5 copyright (c) 2011  asbokid <ballymunboy@gmail.com>

This program comes with asbolutely no warranty; This is free software,
and you are welcome to redistribute it under certain conditions:
GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html

Usage:
 -h, --help             display this text
 -v, --verbose          verbose output
 -d, --debug            debug output
 -s, --size             size of EEPROM {24c32|24c64}
 -e, --erase            erase EEPROM (fill with 0xff)
 -w, --write <filename> write EEPROM with image from filename
 -r, --read  <filename> read EEPROM and save image to filename

Example:  ch341eeprom -v -s 24c64 -w bootrom.bin
~/test> mktestimg > testimg24c64.bin
~/test> xxd -l 128 testimg24c64.bin
00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000010: 1111 1111 1111 1111 1111 1111 1111 1111  ................
00000020: 2222 2222 2222 2222 2222 2222 2222 2222  """"""""""""""""
00000030: 3333 3333 3333 3333 3333 3333 3333 3333  3333333333333333
00000040: 4444 4444 4444 4444 4444 4444 4444 4444  DDDDDDDDDDDDDDDD
00000050: 5555 5555 5555 5555 5555 5555 5555 5555  UUUUUUUUUUUUUUUU
00000060: 6666 6666 6666 6666 6666 6666 6666 6666  ffffffffffffffff
00000070: 7777 7777 7777 7777 7777 7777 7777 7777  wwwwwwwwwwwwwwww
~/test> ch341eeprom -v -s 24c64 -w testimg24c64.bin
Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
Couldn't open device [1a86:5512]
Couldnt configure USB device

Don’t know how libusb works, but the software stops here:

libusb_fill_bulk_transfer(xferBulkIn,  devHandle, BULK_READ_ENDPOINT, ch341inBuffer, 
        EEPROM_READ_BULKIN_BUF_SZ, cbBulkIn, NULL, DEFAULT_TIMEOUT);

    libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, 
        ch341outBuffer, EEPROM_READ_BULKOUT_BUF_SZ,cbBulkOut, NULL, DEFAULT_TIMEOUT);

    fprintf(debugout, "Filled USB transfer structures\n");

    libusb_submit_transfer(xferBulkIn);
    fprintf(debugout, "Submitted BULK IN start packet\n");
    libusb_submit_transfer(xferBulkOut);
    fprintf(debugout, "Submitted BULK OUT setup packet\n");

    readbuf = buffer;

    byteoffset = 0;

    while (byteoffset < bytestoread) {
        fprintf(stdout, "Read [%d] of [%d] bytes      \r", byteoffset, bytestoread);
		ret = libusb_handle_events_timeout(NULL, &tv);

		if (ret < 0 || getnextpkt == -1) {          // indicates an error
            fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret);
            fprintf(stderr, "getnextpkt = %d\n", getnextpkt);
            fprintf(stderr, "USB read error : %s\n", strerror(-ret));
			goto out_deinit;
        }
        if(getnextpkt == 1) {                       // callback function reports a new BULK IN packet received
            getnextpkt = 0;                         //   reset the flag
            readpktcount++;                         //   increment the read packet counter
            byteoffset += EEPROM_READ_BULKIN_BUF_SZ;
            fprintf(debugout, "\nRe-submitting transfer request to BULK IN endpoint\n");
            libusb_submit_transfer(xferBulkIn);     // re-submit request for next BULK IN packet of EEPROM data
            if(syncackpkt)
                syncackpkt = 0;
                                                    // if 4th packet received, we are at end of 0x80 byte data block,
                                                    // if it is not the last block, then resubmit request for data
            if(readpktcount==4 && byteoffset < bytestoread) {
                fprintf(debugout, "\nSubmitting next transfer request to BULK OUT endpoint\n");
                readpktcount = 0;

                memcpy(ch341outBuffer, CH341_EEPROM_READ_NEXT_CMD, CH341_EEPROM_READ_CMD_SZ);
                ch341outBuffer[4] = (uint8_t) (byteoffset >> 8 & 0xff);     // MSB (big-endian) byte address
                ch341outBuffer[5] = (uint8_t) (byteoffset & 0xff);          // LSB of 16-bit    byte address

                libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 
                                    EEPROM_READ_BULKOUT_BUF_SZ, cbBulkOut, NULL, DEFAULT_TIMEOUT);
                
                libusb_submit_transfer(xferBulkOut);// update transfer struct (with new EEPROM page offset)
                                                    // and re-submit next transfer request to BULK OUT endpoint

in this while loop :

while (byteoffset < bytestoread)

getnextpkt remain at 0, so the while keep waiting…

Of the two callback function :

// Callback function for async bulk in comms
void cbBulkIn(struct libusb_transfer *transfer) {
    int i;

    switch(transfer->status) {
        case LIBUSB_TRANSFER_COMPLETED:             
                                                    // display the contents of the BULK IN data buffer
            fprintf(debugout,"\ncbBulkIn(): status %d - Read %d bytes\n",transfer->status,transfer->actual_length);

            for(i=0; i < transfer->actual_length; i++) {
                if(!(i%16))
                    fprintf(debugout, "\n   ");
                fprintf(debugout, "%02x ", transfer->buffer[i]);
            }
            fprintf(debugout, "\n");                           
                                                    // copy read data to our EEPROM buffer
            memcpy(readbuf + byteoffset, transfer->buffer, transfer->actual_length);
            getnextpkt = 1;
            break;
        default:
            fprintf(stderr, "\ncbBulkIn: error : %d\n", transfer->status);
            getnextpkt = -1;
    }
	return; 
}

// Callback function for async bulk out comms
void cbBulkOut(struct libusb_transfer *transfer) {
    syncackpkt = 1;
    fprintf(debugout, "\ncbBulkOut(): Sync/Ack received: status %d\n", transfer->status);
    return;
}

cbBulkIn is never called. (I put a fprintf in to check.)

At this point (with everyone else who worked on this being inactive) I guess that would be me. But I had lockups with libusb in several places where I used it, and found no explanation so far.

Each of these times, porting the code to Haiku native USB Kit (which is quite similar) resulted in working code, but I’m not able to see what the two are doing differently. And also it’s possible that someone updated the libusb recipe at haikuports, checked that it compiles, but not that it actually works. On the other side, the libusb developers would be happy to upstream the Haiku support, but they had trouble setting up a continuous integration bot to check it. So, if someone wants to help them, that would be great too :slight_smile:

4 Likes

i’ll investigate further, but as i said, my knowledge is very limited

Which version was first ported? May be i can try with that.