Date: Fri, 16 Nov 2012 22:47:29 GMT From: "Wojciech A. Koszek" <wkoszek@FreeBSD.org> To: freebsd-gnats-submit@FreeBSD.org Subject: usb/173666: [USB, LIBUSB] usb_reset() behavior different between GNU/Linux and FreeBSD Message-ID: <201211162247.qAGMlTm2057387@red.freebsd.org> Resent-Message-ID: <201211162250.qAGMo07M032649@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 173666 >Category: usb >Synopsis: [USB, LIBUSB] usb_reset() behavior different between GNU/Linux and FreeBSD >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-usb >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Nov 16 22:50:00 UTC 2012 >Closed-Date: >Last-Modified: >Originator: Wojciech A. Koszek >Release: 9.0-RELEASE >Organization: FreeBSD >Environment: FreeBSD seu 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:15:25 UTC 2012 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: I have a driver written for libusb, which works fine under GNU/Linux and libusb. Device: gen0.2: <JSB283 Relay Module J-Works,Inc> at usbus0, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON (I used USB sniffer to uncover traffic based on what Windows was doing) Under Linux usb_reset()+usb_set_configuration() calls works fine. Under FreeBSD I have to disable calling usb_reset(), otherwise usb_set_configuration() fails with I/O error. =========== usb_relay.c ================ #include <sys/param.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libusb.h> #include <usb.h> static int g_debug = 0; #define DBG(...) do { \ if (g_debug == 0) { \ break; \ } \ printf("%s(%d): ", __func__, __LINE__); \ printf(__VA_ARGS__); \ printf("\n"); \ } while (0) enum { CMD_QUERY, CMD_ON, CMD_FLASH, CMD_OFF }; static void usage(void) { printf("./usb_relay <on|off>\n"); exit(1); } static struct usb_device * usb_dev_find(uint32_t look_vid, uint32_t look_pid) { struct usb_bus *busses; struct usb_bus *bus; struct usb_device *dev; struct usb_device_descriptor *desc; uint32_t vid, pid; usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); for (bus = busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { desc = &dev->descriptor; vid = desc->idVendor; pid = desc->idProduct; if ((vid == look_vid) && (pid == look_pid)) { return (dev); } } } return (NULL); } int main(int argc, char **argv) { struct usb_device *dev; struct usb_dev_handle *hptr; int o, ret, state, ep, ac, cmd; uint32_t data[2]; char **av; int i; while ((o = getopt(argc, argv, "dh")) != -1) { switch (o) { case 'd': g_debug++; break; case 'h': usage(); break; default: usage(); break; } } ac = argc - optind; av = argv + optind; cmd = CMD_QUERY; if (ac > 0) { if (strcmp(av[0], "on") == 0) { cmd = CMD_ON; } else if (strcmp(av[0], "off") == 0) { cmd = CMD_OFF; } else if (strcmp(av[0], "flash") == 0) { cmd = CMD_FLASH; } else { abort(); } } dev = usb_dev_find(0x07c3, 0x1283); if (dev == NULL) { printf("J283 not found!\n"); exit(1); } hptr = usb_open(dev); DBG("usb_open returned %p", hptr); #ifdef HAS_RESET ret = usb_reset(hptr); DBG("usb_reset returned %d: %s", ret, libusb_strerror(ret)); #endif ret = usb_set_configuration(hptr, 1); DBG("usb_reset returned %d: %s", ret, libusb_strerror(ret)); ret = usb_claim_interface(hptr, 1); DBG("usb_reset returned %d: %s", ret, libusb_strerror(ret)); data[0] = -1; data[1] = -1; ret = usb_control_msg(hptr, 0xc2, 176, 0x0, 0, (char *)data, 8, 400); DBG("usb_control_msg = %d %08x,%08x", ret, data[0], data[1]); ret = usb_control_msg(hptr, 0xc2, 184, 0x0, 0, (char *)data, 8, 400); DBG("usb_control_msg = %d %08x,%08x", ret, data[0], data[1]); if (cmd == CMD_QUERY) { state = data[0] & 1; printf("%s\n", state ? "on" : "off"); } else if (cmd == CMD_ON) { ret = usb_control_msg(hptr, 0xc2, 183, 0x0, 0, (char *)data, 8, 400); } else if (cmd == CMD_OFF) { ret = usb_control_msg(hptr, 0xc2, 182, 0x0, 0, (char *)data, 8, 400); } else if (cmd == CMD_FLASH) { ret = usb_control_msg(hptr, 0xc2, 177, 0x0, 0, (char *)data, 8, 400); } else { abort(); } exit(0); } >How-To-Repeat: seu# gcc -DHAS_RESET usb_relay.c -o usb_relay.has_reset -lusb seu# ./usb_relay.has_reset -d off && sleep 1 && ./usb_relay.has_reset -d on main(110): usb_open returned 0x28405480 main(113): usb_reset returned 0: Success main(117): usb_reset returned -1: I/O error main(119): usb_reset returned 0: Success main(124): usb_control_msg = -1 ffffffff,ffffffff main(126): usb_control_msg = -1 ffffffff,ffffffff main(110): usb_open returned 0x28405480 main(113): usb_reset returned 0: Success main(117): usb_reset returned -1: I/O error main(119): usb_reset returned 0: Success main(124): usb_control_msg = -1 ffffffff,ffffffff main(126): usb_control_msg = -1 ffffffff,ffffffff seu# seu# gcc usb_relay.c -o usb_relay -lusb seu# ./usb_relay -d off && sleep 1 && ./usb_relay -d on main(110): usb_open returned 0x28405480 main(117): usb_reset returned 0: Success main(119): usb_reset returned 0: Success main(124): usb_control_msg = 5 01000001,ffffff00 main(126): usb_control_msg = 5 01000001,ffffff00 main(110): usb_open returned 0x28405480 main(117): usb_reset returned 0: Success main(119): usb_reset returned 0: Success main(124): usb_control_msg = 5 01000001,ffffff00 main(126): usb_control_msg = 5 01000000,ffffff00 >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211162247.qAGMlTm2057387>