From owner-freebsd-usb@FreeBSD.ORG Mon Oct 29 13:18:13 2012 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6EDD4E6E for ; Mon, 29 Oct 2012 13:18:13 +0000 (UTC) (envelope-from toshi@ruby.ocn.ne.jp) Received: from defer106.ocn.ad.jp (defer106.ocn.ad.jp [125.206.148.14]) by mx1.freebsd.org (Postfix) with ESMTP id 181368FC17 for ; Mon, 29 Oct 2012 13:18:12 +0000 (UTC) Received: from msgw001-01.ocn.ad.jp (msgw001-01.ocn.ad.jp [180.37.203.70]) by defer106.ocn.ad.jp (Postfix) with ESMTP id C080B236361 for ; Mon, 29 Oct 2012 21:54:42 +0900 (JST) Received: from localhost (p16200-ipngn100102sizuokaden.shizuoka.ocn.ne.jp [180.51.199.200]) by msgw001-01.ocn.ad.jp (Postfix) with ESMTP id AAD1444DDAE; Mon, 29 Oct 2012 21:54:35 +0900 (JST) Date: Mon, 29 Oct 2012 21:54:34 +0900 (JST) Message-Id: <20121029.215434.122618874.toshi@ruby.ocn.ne.jp> To: freebsd-usb@freebsd.org Subject: isochronous transfer for UVC camera From: SAITOU Toshihide X-GPG-fingerprint: 34B3 0B6A 8520 F5B0 EBC7 69F6 C055 9F8A 0D49 F8FC X-Mailer: Mew version 6.2.51 on Emacs 22.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Oct 2012 13:18:13 -0000 I'm trying to get the streaming data from the UVC camera, but isochronous transfer callback isn't invoked. Is this lack of parameters to be set or wrong coding for my isochronous transfer? $ uname -a FreeBSD Kingyo.ens.tut.ac.jp 9.1-RC2 FreeBSD 9.1-RC2 #0 r241106: Mon Oct 1 18:26:44 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 ------------------------------------------------------------ /* * $ cc -o ex10 ex10.c -lusb * $ ./ex10 * * [UVC1.5] Universal Serial Bus Device Class Definition for Video Devices, * (UVC 1.5 Class specification.pdf), * . * * [USB2.0] USB 2.0 Specification Universal Serial Bus Revision 2.0 specification, * (usb_20.pdf), . */ #include #include #include #define VID 0x0458 #define PID 0x7081 #define TIMEOUT 500 // 500 ms #define ConfNum 1 // Configuration Number #define IfNum 1 // Interface Number #define AltIfNum 1 // Alternate Interface Number static void cb(struct libusb_transfer *transfer) { printf("\nReceived.\n"); libusb_submit_transfer(transfer); // repeat } int main( int argc, char **argv) { struct libusb_device_descriptor desc; libusb_context *ctx = NULL; libusb_device **deviceLst; ssize_t deviceCnt = 0; libusb_device *camdev = NULL; libusb_device_handle *handle; int attached = 0; uint8_t buf[256]; int i; int rcv; // populate list with the list of usb devices available. libusb_init(&ctx); if ((deviceCnt = libusb_get_device_list(ctx, &deviceLst)) < 0) { fprintf(stderr, "no usb devices found\n"); return; } libusb_set_debug(ctx, 99); // find device for (i = 0; i < deviceCnt; i++) { libusb_get_device_descriptor(deviceLst[i], &desc); if (desc.idVendor == VID && desc.idProduct == PID) { camdev = (libusb_device *)deviceLst[i]; break; } } if (!camdev) { fprintf(stderr, "device not found."); return; } // open device if (libusb_open(camdev, &handle) != 0) { fprintf(stderr, "Unable to open usb device\n"); return; } // if kernel driver is active, detach a kernel driver. if (libusb_kernel_driver_active(handle, 0) == 1) { printf("Detaching kernel driver.\n"); libusb_detach_kernel_driver(handle, 0); attached = 1; } // set the active configuration if (libusb_set_configuration(handle, ConfNum) != 0) { fprintf(stderr, "Set configuration failed."); } // ------------------------------------------------------------ // negotiate the streaming parameters // Device State Transition [UVC1.5, p. 107] // Video Probe and Commit Controls [UVC1.5, p. 134] // set some parameters described to set by the host. [UVC1.5, p. 134] for (i=0; i<48; i++) { buf[i] = 0x00; } buf[0] = 0x01; // what fields shall be kept fixed (0x01: dwFrameInterval) buf[1] = 0x00; // buf[2] = 0x01; // video format index buf[3] = 0x01; // video frame index buf[4] = 0x40; // interval buf[5] = 0x4b; // propose: 0x4c4b40 (500 ms) buf[6] = 0x4c; // agreement: 0x1312d0 (125 ms) buf[7] = 0x00; // // VS_PROBE_CONTROL(0x01) [UVC1.5, p. 161], SET_CUR(0x87) [UVC1.5, p.158] libusb_control_transfer(handle, 0x21, 0x01, 0x0100, 0x0001, buf, 48, TIMEOUT); for (i=0; i<48; i++) { printf("%x ", buf[i]); } printf("\n"); // VS_PROBE_CONTROL(0x01) [UVC1.5, p. 161], GET_CUR(0x81) [UVC1.5, p.158] libusb_control_transfer(handle, 0xa1, 0x81, 0x0100, 0x0001, buf, 48, TIMEOUT); for (i=0; i<48; i++) { printf("%x ", buf[i]); } printf("\n"); // VS_COMMIT_CONTROL(0x02) [UVC1.5, p. 161], SET_CUR(0x01) [UVC1.5, p.158] libusb_control_transfer(handle, 0x21, 0x01, 0x0200, 0x0001, buf, 48, TIMEOUT); for (i=0; i<48; i++) { printf("%x ", buf[i]); } printf("\n"); // VS_COMMIT_CONTROL(0x02) [UVC1.5, p. 161], GET_CUR(0x81) [UVC1.5, p.158] //libusb_control_transfer(handle, 0xa1, 0x81, 0x0200, 0x0001, buf, 48, TIMEOUT); //for (i=0; i<48; i++) { printf("%x ", buf[i]); } printf("\n"); // set interface, set alt interface [USB2.0, p. 250] // are available through synchronous, blocking function // in the libusb, so can not use libusb_control_transfer. // claim an interface in a given libusb_handle. if (libusb_claim_interface(handle, IfNum) != 0) { fprintf(stderr, "Claim interface failed."); } // activate an alternate setting for an interface. if (libusb_set_interface_alt_setting(handle, IfNum, AltIfNum) != 0) { fprintf(stderr, "Activate an alternate setting failed."); } // cam LED is lit here. it looks like ready to send the data. //while (1) {} // ------------------------------------------------------------ // do an isochronous transfer /* High-speed * 1024 bytes data payloads * 1 microframe takes 125 us (8 times per frame). * upto 3 transfer per microframe. * 8 3 1024 1000 ~ */ #define PKT_LEN 0x1400 #define PKTS_PER_XFER 8 struct libusb_transfer *xfer; xfer = libusb_alloc_transfer(PKTS_PER_XFER); uint8_t *data = malloc(PKT_LEN*PKTS_PER_XFER); libusb_fill_iso_transfer( xfer, handle, 0x82, // Interface 1 Alt 1 Endpoint 0 Address 0x82 data, PKT_LEN*PKTS_PER_XFER, PKTS_PER_XFER, cb, NULL, TIMEOUT); if ( (rcv = libusb_submit_transfer(xfer)) != 0) { fprintf(stderr, "failed to submit transfer: %d\n", rcv); } sleep(30); // if we detached kernel driver, reattach. if (attached == 1) { libusb_attach_kernel_driver(handle, 0); } libusb_close(handle); libusb_free_device_list(deviceLst, 1); libusb_exit(ctx); } ------------------------------------------------------------ Interface 1 ... bDescriptorSubType = 0x01 ... bDescriptorSubType = 0x04 . (bFormatIndex: 0x01) ... bDescriptorSubType = 0x05 . (bFrameIndex: 0x01) ... Interface 1 Alt 1 bLength = 0x0009 bDescriptorType = 0x0004 bInterfaceNumber = 0x0001 bAlternateSetting = 0x0001 bNumEndpoints = 0x0001 bInterfaceClass = 0x000e [UVC1.5, p. 156] bInterfaceSubClass = 0x0002 [UVC1.5, p. 156] bInterfaceProtocol = 0x0000 [UVC1.5, p. 156] iInterface = 0x0004 (read from index of string descriptor 4) Endpoint 0 bLength = 0x0007 bDescriptorType = 0x0005 [USB2.0, p. 251, 269-270] bEndpointAddress = 0x0082 bmAttributes = 0x0005 wMaxPacketSize = 0x1400 bInterval = 0x0001 bRefresh = 0x0000 bSynchAddress = 0x0000 ------------------------------------------------------------ $ sysctl hw.usb.debug=1 $ ./ex10 1 0 1 1 40 4b 4c 0 30 0 62 40 0 0 0 0 1 0 0 0 0 0 0 0 0 c8 61 40 0 0 0 0 90 6c a3 40 0 0 0 0 90 d2 ff ff ff 7f 0 0 1 0 1 1 d0 12 13 0 0 0 0 0 0 0 0 0 0 0 0 60 9 0 0 c 0 0 61 40 0 0 0 0 90 6c a3 40 0 0 0 0 90 d2 ff ff ff 7f 0 0 1 0 1 1 d0 12 13 0 0 0 0 0 0 0 0 0 0 0 0 60 9 0 0 c 0 0 61 40 0 0 0 0 90 6c a3 40 0 0 0 0 90 d2 ff ff ff 7f 0 0 $ sysctl hw.usb.debug=0 $ fgrep 'bEndpointAddress=0x82' /var/log/messages ------------------------------------------------------------ kernel: usb_dump_endpoint: endpoint=0xfffffe00781f7a50 edesc=0xfffffe0007cd3704 isoc_next=112 toggle_next=0 bEndpointAddress=0x82 kernel: usb_dump_queue: endpoint=0xfffffe00781f7a50 xfer: kernel: usbd_transfer_submit: open kernel: usbd_pipe_enter: enter kernel: usbd_pipe_start: start kernel: usbd_transfer_done: err=USB_ERR_NORMAL_COMPLETION kernel: usbd_callback_wrapper_sub: xfer=0xffffff8002e28148 endpoint=0xfffffe00781f7a50 sts=0 alen=0, slen=0, afrm=8, nfrm=8 kernel: usbd_transfer_done: err=USB_ERR_NORMAL_COMPLETION kernel: usbd_callback_wrapper_sub: xfer=0xfffffe00077f6948 endpoint=0xfffffe0007920a80 sts=0 alen=4, slen=4, afrm=1, nfrm=1 kernel: usbd_transfer_submit: xfer=0xfffffe00077f6948, endpoint=0xfffffe0007920a80, nframes=1, dir=read kernel: usb_dump_endpoint: endpoint=0xfffffe0007920a80 edesc=0xfffffe000792951b isoc_next=0 toggle_next=0 bEndpointAddress=0x81 kernel: usb_dump_queue: endpoint=0xfffffe0007920a80 xfer: kernel: usbd_pipe_enter: enter kernel: usbd_pipe_start: start ... kernel: usbd_pipe_enter: enter kernel: usbd_pipe_start: start kernel: usbd_do_request_flags: Handle Request function is set last message repeated 9 times --- SAITOU Toshihide