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