Problem with libusb on FreeBSD?

Alexander Shiryaev coumarin at gmail.com
Mon Aug 6 09:37:33 UTC 2007


I have the same problem, with other device model.

If do not touch control endpoint for interrupt and bulk endpoints search 
(i.e. open /dev/ugen0.1 and /dev/igen0.2 immediately), then there is no 
problems.

For example, this test will be passed:

#include <sys/types.h>
#include <sys/ioctl.h>
#include <dev/usb/usb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#include <stdio.h>
#include <err.h>
#include <assert.h>

#define OUT_BULK_DEV "/dev/ugen0.2"
#define IN_INTR_DEV "/dev/ugen0.1"
#define IN_BULK_DEV "/dev/ugen0.3"

struct packet {
     u_int8_t packet_type;
     u_int8_t reserved1[3];
     u_int16_t packet_id;
     u_int8_t reserved2[2];
     u_int32_t data_size;
};

#define USB_PROTOCOL_LAYER 0
#define APPLICATION_LAYER 20

#define PID_DATA_AVAILABLE 2
#define PID_START_SESSION 5
#define PID_SESSION_STARTED 6

#define PID_PROTOCOL_ARRAY 253
#define PID_PRODUCT_RQST 254
#define PID_PRODUCT_DATA 255

static u_int8_t const START_SESSION_REQ[] =
     { USB_PROTOCOL_LAYER, 0, 0, 0, PID_START_SESSION, 0, 0, 0, 0, 0, 0, 
0 };

static u_int8_t const A000_REQ[] =
     { APPLICATION_LAYER, 0, 0, 0, PID_PRODUCT_RQST, 0, 0, 0, 0, 0, 0, 0 };

#define BUF_SIZE 1024

static int out, in_intr, in_bulk;

static void dump (u_int8_t buf[], u_int32_t len)
{
     u_int32_t i;

     if (len == 0) {
         printf("EMPTY\n");
     } else {
         for (i = 0; i < len; i++) {
             printf("%2x", buf[i]);
             if (i % 16 == 15)
                 printf("\n");
             else
                 printf(" ");
         }
         if (len % 16 != 0)
             printf("\n");
     }
}

static void send_req (u_int8_t const req[], int len)
{
     size_t done;

     done = write(out, req, len);
     if (done == -1)
         err(1, NULL);
     printf("write: %d\n", done);
     assert(done == len);
}

static int response_received (u_int8_t packet_type, u_int16_t packet_id, 
u_int8_t data[], int len)
{
     switch (packet_type) {
     case USB_PROTOCOL_LAYER:
         switch (packet_id) {
         case PID_DATA_AVAILABLE:
             printf("data available\n");
             errx(1, "not implemented"); /* TODO: switch input to in_bulk */
             break;
         case PID_SESSION_STARTED:
             printf("session started\n");
             send_req(A000_REQ, sizeof(A000_REQ));
             break;
         default:
             errx(1, "invalid packet id");
         }
         break;
     case APPLICATION_LAYER:
         switch (packet_id) {
         case PID_PRODUCT_DATA:
             break;
         case PID_PROTOCOL_ARRAY:
             return 1;
             break;
         default:
             errx(1, "invalid packet id");
         }
         break;
     default:
         errx(1, "invalid packet type");
     }
     return 0;
}

static size_t read1 (int in, void *buf, int len)
{
     int done, d;

     done = 0;
     while (done < len) {
         d = read(in, buf, len - done);
         printf("read1: %d\n", d);
         done += d;
     };

     return done;
}

static void start_loop ()
{
     int terminate = 0;
     size_t done;
     struct packet packet;
     u_int8_t buf[BUF_SIZE];

     do {
         done = read1(in_intr, buf, sizeof(packet));
         if (done == -1)
             err(1, NULL);
         printf("intr read: %d\n", done);
         assert(done == sizeof(packet));
         dump(buf, done);

         memcpy(&packet, buf, done);

         if ((packet.reserved1[0] != 0) || (packet.reserved1[1] != 0)
             || (packet.reserved1[2] != 0) || (packet.reserved2[0] != 0)
             || (packet.reserved2[1] != 0)) {
                 errx(1, "inalid packet");
         }

         done = read1(in_intr, buf, packet.data_size);
         if (done == -1)
             err(1, NULL);
         printf("intr expected: %d, intr read: %d\n", packet.data_size, 
done);
         assert(done == packet.data_size);
         dump(buf, done);

         terminate = response_received(packet.packet_type, 
packet.packet_id, buf, packet.data_size);
     } while (!terminate);
}

int main ()
{
     out = open(OUT_BULK_DEV, O_WRONLY);
     if (out == -1)
         err(1, OUT_BULK_DEV);

     in_intr = open(IN_INTR_DEV, O_RDONLY);
     if (in_intr == -1)
         err(1, IN_INTR_DEV);

     in_bulk = open(IN_BULK_DEV, O_RDONLY);
     if (in_bulk == -1)
         err(1, IN_BULK_DEV);

     send_req(START_SESSION_REQ, sizeof(START_SESSION_REQ));

     start_loop();

     printf("all done\n");

     return 0;
}


Best regards, Alexander.


More information about the freebsd-usb mailing list