Commits

Cliff Biffle committed 725e8f7

Brought the drivers into the project, after having too much trouble with cross-project dependencies.

Comments (0)

Files changed (11)

+//
+//  KFContext.h
+//  KinectFW
+//
+//  Created by Cliff L. Biffle on 2010-11-23.
+//  Copyright 2010 Cliff L. Biffle. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "libfreenect.h"
+
+@protocol KFKinectDelegate;
+
+@interface KFKinect : NSObject {
+	uint8_t *_depthBuffer;
+	uint8_t *_rgbBuffer;
+	
+	freenect_context *_context;
+	freenect_device *_device;
+	
+	BOOL _running;
+	
+	id<KFKinectDelegate> delegate;
+}
+
+- init;
+- (void)openWithDepthBuffer: (void *)depthBuffer rgbBuffer: (void *)rgbBuffer;
+- (void)close;
+
+@property(assign) id<KFKinectDelegate> delegate;
+
+@end
+
+@protocol KFKinectDelegate
+- (void)depthFieldUpdated: (KFKinect *)kinect;
+@end
+
+//
+//  KFContext.m
+//  KinectFW
+//
+//  Created by Cliff L. Biffle on 2010-11-23.
+//  Copyright 2010 Cliff L. Biffle. All rights reserved.
+//
+
+#import "KFKinect.h"
+#import "libfreenect.h"
+
+@interface KFKinect (Private)
+- (void)ioThread;
+- (void)depthCallback: (freenect_depth *)buffer;
+- (void)rgbCallback: (freenect_pixel *)buffer;
+@end
+
+static void depthCallback(freenect_device *dev, freenect_depth *depth, uint32_t timestamp) {
+    [(KFKinect *)freenect_get_user(dev) depthCallback:depth];
+}
+static void rgbCallback(freenect_device *dev, freenect_pixel *rgb, uint32_t timestamp) {
+    [(KFKinect *)freenect_get_user(dev) rgbCallback:rgb];
+}
+
+@implementation KFKinect
+
+- init
+{
+	if (![super init]) return nil;
+	
+	_running = NO;
+	delegate = nil;
+	return self;
+}
+- (void)openWithDepthBuffer: (void *)depthBuffer rgbBuffer: (void *)rgbBuffer
+{
+	_depthBuffer = depthBuffer;
+	_rgbBuffer = rgbBuffer;
+	[NSThread detachNewThreadSelector:@selector(ioThread) toTarget:self withObject:nil];
+}
+- (void)close
+{
+	_running = NO;
+}
+
+@synthesize delegate;
+
+@end
+
+@implementation KFKinect (Private)
+
+- (void)ioThread
+{
+	if(freenect_init(&_context, NULL) >= 0) {
+        if(freenect_open_device(_context, &_device, 0) >= 0) {
+            freenect_set_user(_device, self);
+            freenect_set_depth_callback(_device, depthCallback);
+            freenect_set_rgb_callback(_device, rgbCallback);
+            freenect_set_rgb_format(_device, FREENECT_FORMAT_RGB);
+            freenect_set_depth_format(_device, FREENECT_FORMAT_11_BIT);
+            freenect_start_depth(_device);
+            freenect_start_rgb(_device);
+            
+          NSLog(@"wheeee");
+          
+            while(!_running && freenect_process_events(_context) >= 0);
+            
+            freenect_close_device(_device);
+            _device = NULL;
+            
+            NSLog(@"Stopped");
+        } else {
+            NSLog(@"Could not open device");
+        }
+        freenect_shutdown(_context);
+        _context = NULL;
+    } else {
+		NSLog(@"Could not init device");
+	}
+}
+
+- (void)depthCallback: (freenect_depth *)buffer
+{
+	if (_depthBuffer) memcpy(_depthBuffer, buffer, FREENECT_DEPTH_SIZE);
+	[delegate depthFieldUpdated: self];
+}
+
+- (void)rgbCallback: (freenect_pixel *)buffer
+{
+	if (_rgbBuffer) memcpy(_rgbBuffer, buffer, FREENECT_RGB_SIZE);
+}
+
+@end
+

driver/libfreenect/accelerometers.c

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "freenect_internal.h"
+#define GRAVITY 9.80665
+
+int freenect_get_raw_accelerometers(freenect_device *dev, int16_t* x, int16_t* y, int16_t* z)
+{
+	unsigned char buf[10];
+	uint16_t ux, uy, uz;
+	int ret = fnusb_control(&dev->usb_motor, 0xC0, 0x32, 0x0, 0x0, buf, 10);
+	if (ret != 10)
+		printf("Error in accelerometer reading, libusb_control_transfer returned %d\n", ret);
+	
+	ux = ((uint16_t)buf[2] << 8) | buf[3];
+	uy = ((uint16_t)buf[4] << 8) | buf[5];
+	uz = ((uint16_t)buf[6] << 8) | buf[7];
+	*x = (int16_t)ux;
+	*y = (int16_t)uy;
+	*z = (int16_t)uz;
+	
+	return ret;
+}
+
+int freenect_get_mks_accelerometers(freenect_device *dev, double* x, double* y, double* z)
+{
+        //the documentation for the accelerometer (http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf) 
+        //states there are 819 counts/g  
+	int16_t ix, iy, iz;
+        int ret = freenect_get_raw_accelerometers(dev,&ix,&iy,&iz);
+
+	*x = (double)ix/FREENECT_COUNTS_PER_G*GRAVITY;
+	*y = (double)iy/FREENECT_COUNTS_PER_G*GRAVITY;
+	*z = (double)iz/FREENECT_COUNTS_PER_G*GRAVITY;
+
+	return ret;
+}
+
+

driver/libfreenect/cameras.c

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "freenect_internal.h"
+
+struct pkt_hdr {
+	uint8_t magic[2];
+	uint8_t pad;
+	uint8_t flag;
+	uint8_t unk1;
+	uint8_t seq;
+	uint8_t unk2;
+	uint8_t unk3;
+	uint32_t timestamp;
+};
+
+extern const struct caminit inits[];
+extern const int num_inits;
+
+static int stream_process(packet_stream *strm, uint8_t *pkt, int len)
+{
+	if (len < 12)
+		return 0;
+
+	struct pkt_hdr *hdr = (void*)pkt;
+	uint8_t *data = pkt + sizeof(*hdr);
+	int datalen = len - sizeof(*hdr);
+
+	if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
+		//printf("[Stream %02x] Invalid magic %02x%02x\n", strm->flag, hdr->magic[0], hdr->magic[1]);
+		return 0;
+	}
+
+	//printf("[Stream %02x] %02x\n", strm->flag, hdr->flag);
+
+	uint8_t sof = strm->flag|1;
+	uint8_t mof = strm->flag|2;
+	uint8_t eof = strm->flag|5;
+
+	// sync if required, dropping packets until SOF
+	if (!strm->synced) {
+		if (hdr->flag != sof) {
+			//printf("[Stream %02x] not synced yet...\n", strm->flag);
+			return 0;
+		}
+		strm->synced = 1;
+		strm->seq = hdr->seq;
+		strm->pkt_num = 0;
+		strm->valid_pkts = 0;
+		strm->got_pkts = 0;
+	}
+
+	int got_frame = 0;
+
+	// handle lost packets
+	if (strm->seq != hdr->seq) {
+		uint8_t lost = strm->seq - hdr->seq;
+		//printf("[Stream %02x] lost %d packets\n", strm->flag, lost);
+		if (lost > 5) {
+			//printf("[Stream %02x] lost too many packets, resyncing...\n", strm->flag);
+			strm->synced = 0;
+			return 0;
+		}
+		strm->seq = hdr->seq;
+		int left = strm->pkts_per_frame - strm->pkt_num;
+		if (left <= lost) {
+			strm->pkt_num = lost - left;
+			strm->valid_pkts = strm->got_pkts;
+			strm->got_pkts = 0;
+			got_frame = 1;
+			strm->timestamp = strm->last_timestamp;
+		} else {
+			strm->pkt_num += lost;
+		}
+	}
+
+	// check the header to make sure it's what we expect
+	if (!(strm->pkt_num == 0 && hdr->flag == sof) &&
+	    !(strm->pkt_num == strm->pkts_per_frame-1 && hdr->flag == eof) &&
+	    !(strm->pkt_num > 0 && strm->pkt_num < strm->pkts_per_frame-1 && hdr->flag == mof)) {
+		//printf("[Stream %02x] Inconsistent flag %02x with %d packets in buf (%d total), resyncing...\n",
+		//       strm->flag, hdr->flag, strm->pkt_num, strm->pkts_per_frame);
+		strm->synced = 0;
+		return 0;
+	}
+
+	// copy data
+	if (datalen > strm->pkt_size) {
+		//printf("[Stream %02x] Expected %d data bytes, but got %d. Dropping...\n", strm->flag, strm->pkt_size, datalen);
+		return 0;
+	}
+
+	//if (datalen != strm->pkt_size && hdr->flag != eof)
+		//printf("[Stream %02x] Expected %d data bytes, but got only %d\n", strm->flag, strm->pkt_size, datalen);
+
+	uint8_t *dbuf = strm->buf + strm->pkt_num * strm->pkt_size;
+	memcpy(dbuf, data, datalen);
+
+	strm->pkt_num++;
+	strm->seq++;
+	strm->got_pkts++;
+
+	strm->last_timestamp = hdr->timestamp;
+
+	if (strm->pkt_num == strm->pkts_per_frame) {
+		strm->pkt_num = 0;
+		strm->valid_pkts = strm->got_pkts;
+		strm->got_pkts = 0;
+		strm->timestamp = hdr->timestamp;
+		return 1;
+	} else {
+		return got_frame;
+	}
+}
+
+// Unpack buffer of (vw bit) data into padded 16bit buffer.
+#define CONVERT_PACKED_BUFFER_TO_16_BIT(depth_raw, depth_frame, vw) {\
+		const int mask = (1 << vw) - 1; \
+		int i; \
+		int bitshift = 0; \
+		for (i=0; i<(640*480); i++) { \
+			int idx = (i*vw)/8; \
+			uint32_t word = (depth_raw[idx]<<(16)) | (depth_raw[idx+1]<<8) | depth_raw[idx+2]; \
+			depth_frame[i] = ((word >> (((3*8)-vw)-bitshift)) & mask); \
+			bitshift = (bitshift + vw) % 8; \
+		} \
+}
+
+static void depth_process(freenect_device *dev, uint8_t *pkt, int len)
+{
+	if (len == 0)
+		return;
+
+	int got_frame = stream_process(&dev->depth_stream, pkt, len);
+
+	if (!got_frame)
+		return;
+
+	//printf("GOT DEPTH FRAME %d/%d packets arrived, TS %08x\n",
+	//      dev->depth_stream.valid_pkts, dev->depth_stream.pkts_per_frame, dev->depth_stream.timestamp);
+
+	if( dev->depth_format == FREENECT_FORMAT_11_BIT )
+		CONVERT_PACKED_BUFFER_TO_16_BIT(dev->depth_raw, dev->depth_frame, 11)
+	else
+		CONVERT_PACKED_BUFFER_TO_16_BIT(dev->depth_raw, dev->depth_frame, 10)
+
+	if (dev->depth_cb)
+		dev->depth_cb(dev, dev->depth_frame, dev->depth_stream.timestamp);
+}
+
+static void rgb_process(freenect_device *dev, uint8_t *pkt, int len)
+{
+	int x,y,i;
+	if (len == 0)
+		return;
+
+	int got_frame = stream_process(&dev->rgb_stream, pkt, len);
+
+	if (!got_frame)
+		return;
+
+	//printf("GOT RGB FRAME %d/%d packets arrived, TS %08x\n", dev->rgb_stream.valid_pkts,
+	//       dev->rgb_stream.pkts_per_frame, dev->rgb_stream.timestamp);
+
+	uint8_t *rgb_frame = NULL;
+
+	if (dev->rgb_format == FREENECT_FORMAT_BAYER) {
+		rgb_frame = dev->rgb_raw;
+	} else {
+		rgb_frame = dev->rgb_frame;
+		/* Pixel arrangement:
+		 * G R G R G R G R
+		 * B G B G B G B G
+		 * G R G R G R G R
+		 * B G B G B G B G
+		 * G R G R G R G R
+		 * B G B G B G B G
+		 */
+		for (y=0; y<480; y++) {
+			for (x=0; x<640; x++) {
+				i = (y*640+x);
+				if ((y&1) == 0) {
+					if ((x&1) == 0) {
+						// topleft G pixel
+						uint8_t rr = dev->rgb_raw[i+1];
+						uint8_t rl = x == 0 ? rr : dev->rgb_raw[i-1];
+						uint8_t bb = dev->rgb_raw[i+640];
+						uint8_t bt = y == 0 ? bb : dev->rgb_raw[i-640];
+						rgb_frame[3*i+0] = (rl+rr)>>1;
+						rgb_frame[3*i+1] = dev->rgb_raw[i];
+						rgb_frame[3*i+2] = (bt+bb)>>1;
+					} else {
+						// R pixel
+						uint8_t gl = dev->rgb_raw[i-1];
+						uint8_t gr = x == 639 ? gl : dev->rgb_raw[i+1];
+						uint8_t gb = dev->rgb_raw[i+640];
+						uint8_t gt = y == 0 ? gb : dev->rgb_raw[i-640];
+						uint8_t bbl = dev->rgb_raw[i+639];
+						uint8_t btl = y == 0 ? bbl : dev->rgb_raw[i-641];
+						uint8_t bbr = x == 639 ? bbl : dev->rgb_raw[i+641];
+						uint8_t btr = x == 639 ? btl : y == 0 ? bbr : dev->rgb_raw[i-639];
+						rgb_frame[3*i+0] = dev->rgb_raw[i];
+						rgb_frame[3*i+1] = (gl+gr+gb+gt)>>2;
+						rgb_frame[3*i+2] = (bbl+btl+bbr+btr)>>2;
+					}
+				} else {
+					if ((x&1) == 0) {
+						// B pixel
+						uint8_t gr = dev->rgb_raw[i+1];
+						uint8_t gl = x == 0 ? gr : dev->rgb_raw[i-1];
+						uint8_t gt = dev->rgb_raw[i-640];
+						uint8_t gb = y == 479 ? gt : dev->rgb_raw[i+640];
+						uint8_t rtr = dev->rgb_raw[i-639];
+						uint8_t rbr = y == 479 ? rtr : dev->rgb_raw[i-641];
+						uint8_t rtl = x == 0 ? rtr : dev->rgb_raw[i-641];
+						uint8_t rbl = x == 0 ? rbr : y == 479 ? rtl : dev->rgb_raw[i+639];
+						rgb_frame[3*i+0] = (rbl+rtl+rbr+rtr)>>2;
+						rgb_frame[3*i+1] = (gl+gr+gb+gt)>>2;
+						rgb_frame[3*i+2] = dev->rgb_raw[i];
+					} else {
+						// botright G pixel
+						uint8_t bl = dev->rgb_raw[i-1];
+						uint8_t br = x == 639 ? bl : dev->rgb_raw[i+1];
+						uint8_t rt = dev->rgb_raw[i-640];
+						uint8_t rb = y == 479 ? rt : dev->rgb_raw[i+640];
+						rgb_frame[3*i+0] = (rt+rb)>>1;
+						rgb_frame[3*i+1] = dev->rgb_raw[i];
+						rgb_frame[3*i+2] = (bl+br)>>1;
+					}
+				}
+			}
+		}
+	}
+
+	if (dev->rgb_cb)
+		dev->rgb_cb(dev, rgb_frame, dev->rgb_stream.timestamp);
+}
+
+struct cam_hdr {
+	uint8_t magic[2];
+	uint16_t len;
+	uint16_t cmd;
+	uint16_t tag;
+};
+
+static void send_init(freenect_device *dev)
+{
+	int i, j, ret;
+	uint8_t obuf[0x400];
+	uint8_t ibuf[0x200];
+	struct cam_hdr *chdr = (void*)obuf;
+	struct cam_hdr *rhdr = (void*)ibuf;
+
+	ret = fnusb_control(&dev->usb_cam, 0x80, 0x06, 0x3ee, 0, ibuf, 0x12);
+	//printf("First xfer: %d\n", ret);
+
+	chdr->magic[0] = 0x47;
+	chdr->magic[1] = 0x4d;
+	
+	for (i=0; i<num_inits; i++) {
+		const struct caminit *ip = &inits[i];
+		chdr->cmd = ip->command;
+		chdr->tag = ip->tag;
+		chdr->len = ip->cmdlen / 2;
+		memcpy(obuf+sizeof(*chdr), ip->cmddata, ip->cmdlen);
+
+		if( i==6 )
+		{
+			// Choose 10bit or 11 bit depth output
+			obuf[sizeof(*chdr) + 2] = dev->depth_format == FREENECT_FORMAT_11_BIT ? 0x03 : 0x02;
+		}
+
+		ret = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, ip->cmdlen + sizeof(*chdr));
+		//printf("CTL CMD %04x %04x = %d\n", chdr->cmd, chdr->tag, ret);
+		do {
+			ret = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200);
+		} while (ret == 0);
+		//printf("CTL RES = %d\n", ret);
+		if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
+			//printf("Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]);
+			continue;
+		}
+		if (rhdr->cmd != chdr->cmd) {
+			//printf("Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd);
+			continue;
+		}
+		if (rhdr->tag != chdr->tag) {
+			//printf("Bad tag %04x != %04x\n", rhdr->tag, chdr->tag);
+			continue;
+		}
+		if (rhdr->len != (ret-sizeof(*rhdr))/2) {
+			//printf("Bad len %04x != %04x\n", rhdr->len, (int)(ret-sizeof(*rhdr))/2);
+			continue;
+		}
+		if (rhdr->len != (ip->replylen/2) || memcmp(ibuf+sizeof(*rhdr), ip->replydata, ip->replylen)) {
+			//printf("Expected: ");
+			for (j=0; j<ip->replylen; j++) {
+				//printf("%02x ", ip->replydata[j]);
+			}
+			//printf("\nGot:      ");
+			for (j=0; j<(rhdr->len*2); j++) {
+				//printf("%02x ", ibuf[j+sizeof(*rhdr)]);
+			}
+			//printf("\n");
+		}
+	}
+	dev->cam_inited = 1;
+}
+
+int freenect_start_depth(freenect_device *dev)
+{
+	int res;
+
+	dev->depth_stream.buf = dev->depth_raw;
+	dev->depth_stream.pkts_per_frame =
+			dev->depth_format == FREENECT_FORMAT_11_BIT ?
+			DEPTH_PKTS_11_BIT_PER_FRAME : DEPTH_PKTS_10_BIT_PER_FRAME;
+	dev->depth_stream.pkt_size = DEPTH_PKTDSIZE;
+	dev->depth_stream.synced = 0;
+	dev->depth_stream.flag = 0x70;
+
+	res = fnusb_start_iso(&dev->usb_cam, &dev->depth_isoc, depth_process, 0x82, NUM_XFERS, PKTS_PER_XFER, DEPTH_PKTBUF);
+
+	if(!dev->cam_inited)
+		send_init(dev);
+	return res;
+}
+int freenect_start_rgb(freenect_device *dev)
+{
+	int res;
+
+	dev->rgb_stream.buf = dev->rgb_raw;
+	dev->rgb_stream.pkts_per_frame = RGB_PKTS_PER_FRAME;
+	dev->rgb_stream.pkt_size = RGB_PKTDSIZE;
+	dev->rgb_stream.synced = 0;
+	dev->rgb_stream.flag = 0x80;
+
+	res = fnusb_start_iso(&dev->usb_cam, &dev->rgb_isoc, rgb_process, 0x81, NUM_XFERS, PKTS_PER_XFER, RGB_PKTBUF);
+
+	if(!dev->cam_inited)
+		send_init(dev);
+	return res;
+}
+
+int freenect_stop_depth(freenect_device *dev)
+{
+	printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
+	return 0;
+}
+int freenect_stop_rgb(freenect_device *dev)
+{
+	printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
+	return 0;
+}
+
+void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb)
+{
+	dev->depth_cb = cb;
+}
+
+void freenect_set_rgb_callback(freenect_device *dev, freenect_rgb_cb cb)
+{
+	dev->rgb_cb = cb;
+}
+
+int freenect_set_rgb_format(freenect_device *dev, freenect_rgb_format fmt)
+{
+	dev->rgb_format = fmt;
+	return 0;
+}
+
+int freenect_set_depth_format(freenect_device *dev, freenect_depth_format fmt)
+{
+	dev->depth_format = fmt;
+	return 0;
+}

driver/libfreenect/core.c

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "freenect_internal.h"
+
+int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx)
+{
+	*ctx = malloc(sizeof(freenect_context));
+	if (!ctx)
+		return -1;
+
+	memset(*ctx, 0, sizeof(freenect_context));
+
+	return fnusb_init(&(*ctx)->usb, usb_ctx);
+}
+
+int freenect_shutdown(freenect_context *ctx)
+{
+	printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
+	return 0;
+}
+
+int freenect_process_events(freenect_context *ctx)
+{
+	return fnusb_process_events(&ctx->usb);
+}
+
+int freenect_num_devices(freenect_context *ctx)
+{
+  libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
+  ssize_t cnt = libusb_get_device_list (ctx->usb.ctx, &devs); //get the list of devices
+  if (cnt < 0)
+    return (-1);
+
+  int nr = 0, i = 0;
+  struct libusb_device_descriptor desc;
+  for (i = 0; i < cnt; ++i)
+  {
+    int r = libusb_get_device_descriptor (devs[i], &desc);
+    if (r < 0)
+      continue;
+    if (desc.idVendor == MS_MAGIC_VENDOR && desc.idProduct == MS_MAGIC_CAMERA_PRODUCT)
+      nr++;
+  }
+
+  libusb_free_device_list (devs, 1);  // free the list, unref the devices in it
+
+	return (nr);
+}
+
+int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index)
+{
+	int res;
+	freenect_device *pdev = malloc(sizeof(freenect_device));
+	if (!pdev)
+		return -1;
+
+	memset(pdev, 0, sizeof(*pdev));
+
+	pdev->parent = ctx;
+
+	res = fnusb_open_subdevices(pdev, index);
+
+	if (res < 0) {
+		free(pdev);
+		return res;
+	} else {
+		*dev = pdev;
+		return 0;
+	}
+}
+
+int freenect_close_device(freenect_device *dev)
+{
+	printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
+	return 0;
+}
+
+void freenect_set_user(freenect_device *dev, void *user)
+{
+	dev->user_data = user;
+}
+void *freenect_get_user(freenect_device *dev)
+{
+	return dev->user_data;
+}
+

driver/libfreenect/freenect_internal.h

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#ifndef FREENECT_INTERNAL_H
+#define FREENECT_INTERNAL_H
+
+#include <stdint.h>
+
+#include "libfreenect.h"
+
+typedef void (*fnusb_iso_cb)(freenect_device *dev, uint8_t *buf, int len);
+
+#include "usb_libusb10.h"
+
+struct _freenect_context {
+	fnusb_ctx usb;
+};
+
+#define DEPTH_RAW_10_BIT_SIZE 384000
+#define DEPTH_RAW_11_BIT_SIZE 422400
+#define FRAME_H FREENECT_FRAME_H
+#define FRAME_W FREENECT_FRAME_W
+#define FRAME_PIX FREENECT_FRAME_PIX
+
+#define DEPTH_PKTSIZE 1760
+#define RGB_PKTSIZE 1920
+
+#define DEPTH_PKTDSIZE (DEPTH_PKTSIZE-12)
+#define RGB_PKTDSIZE (RGB_PKTSIZE-12)
+
+#define DEPTH_PKTS_10_BIT_PER_FRAME ((DEPTH_RAW_10_BIT_SIZE+DEPTH_PKTDSIZE-1)/DEPTH_PKTDSIZE)
+#define DEPTH_PKTS_11_BIT_PER_FRAME ((DEPTH_RAW_11_BIT_SIZE+DEPTH_PKTDSIZE-1)/DEPTH_PKTDSIZE)
+#define RGB_PKTS_PER_FRAME ((FRAME_PIX+RGB_PKTDSIZE-1)/RGB_PKTDSIZE)
+
+#define MS_MAGIC_VENDOR 0x45e
+#define MS_MAGIC_CAMERA_PRODUCT 0x02ae
+#define MS_MAGIC_MOTOR_PRODUCT 0x02b0
+
+typedef struct {
+	uint8_t flag;
+	int synced;
+	uint8_t seq;
+	int got_pkts;
+	int pkt_num;
+	int pkts_per_frame;
+	int pkt_size;
+	int valid_pkts;
+	uint32_t last_timestamp;
+	uint32_t timestamp;
+	uint8_t *buf;
+} packet_stream;
+
+struct _freenect_device {
+	freenect_context *parent;
+	void *user_data;
+
+	// Cameras
+	fnusb_dev usb_cam;
+	fnusb_isoc_stream depth_isoc;
+	fnusb_isoc_stream rgb_isoc;
+
+	freenect_depth_cb depth_cb;
+	freenect_rgb_cb rgb_cb;
+	freenect_rgb_format rgb_format;
+	freenect_depth_format depth_format;
+
+	int cam_inited;
+
+	packet_stream depth_stream;
+	uint8_t depth_raw[DEPTH_RAW_11_BIT_SIZE];
+	uint16_t depth_frame[FRAME_PIX];
+
+	packet_stream rgb_stream;
+	uint8_t rgb_raw[FRAME_PIX];
+	uint8_t rgb_frame[3*FRAME_PIX];
+
+	// Audio
+	// Motor
+	fnusb_dev usb_motor;
+
+};
+
+struct caminit {
+	uint16_t command;
+	uint16_t tag;
+	int cmdlen;
+	int replylen;
+	uint8_t cmddata[1024];
+	uint8_t replydata[1024];
+};
+
+
+
+
+
+#endif

driver/libfreenect/inits.c

+#include "freenect_internal.h"
+
+const struct caminit inits[] = {
+	{
+		0x03, 0x1267, 4, 2,
+		{0x06, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1268, 4, 2,
+		{0x12, 0x00, 0x03, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1269, 4, 2,
+		{0x13, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x126a, 4, 2,
+		{0x14, 0x00, 0x1e, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x126b, 4, 2,
+		{0x06, 0x00, 0x02, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x126e, 4, 2,
+		{0x06, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x126f, 4, 2,
+		{0x12, 0x00, 0x03, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1270, 4, 2,
+		{0x13, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1271, 4, 2,
+		{0x14, 0x00, 0x1e, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1272, 4, 2,
+		{0x16, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1273, 4, 2,
+		{0x18, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1274, 4, 2,
+		{0x02, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1275, 4, 2,
+		{0x05, 0x01, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1276, 4, 2,
+		{0x24, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1277, 4, 2,
+		{0x2d, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1278, 4, 2,
+		{0x06, 0x00, 0x02, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1279, 4, 2,
+		{0x05, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127a, 4, 2,
+		{0x0c, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127b, 4, 2,
+		{0x0d, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127c, 4, 2,
+		{0x0e, 0x00, 0x1e, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127d, 4, 2,
+		{0x05, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127e, 4, 2,
+		{0x47, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x127f, 4, 2,
+		{0x0c, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1280, 4, 2,
+		{0x05, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1281, 4, 2,
+		{0x0d, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1282, 4, 2,
+		{0x0e, 0x00, 0x1e, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1283, 4, 2,
+		{0x05, 0x00, 0x01, 0x00},
+		{0x00, 0x00},
+	},
+	{
+		0x03, 0x1284, 4, 2,
+		{0x47, 0x00, 0x00, 0x00},
+		{0x00, 0x00},
+	},
+};
+
+const int num_inits = 28;
+

driver/libfreenect/libfreenect.h

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#ifndef LIBFREENECT_H
+#define LIBFREENECT_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t freenect_depth;
+typedef uint8_t freenect_pixel;
+
+#define FREENECT_FRAME_W 640
+#define FREENECT_FRAME_H 480
+#define FREENECT_FRAME_PIX (FREENECT_FRAME_H*FREENECT_FRAME_W)
+#define FREENECT_RGB_SIZE (FREENECT_FRAME_PIX*3)
+#define FREENECT_BAYER_SIZE (FREENECT_FRAME_PIX)
+#define FREENECT_DEPTH_SIZE (FREENECT_FRAME_PIX*sizeof(freenect_depth))
+#define FREENECT_COUNTS_PER_G 819
+
+typedef enum {
+	FREENECT_FORMAT_RGB = 0,
+	FREENECT_FORMAT_BAYER = 1,
+} freenect_rgb_format;
+
+typedef enum {
+    LED_OFF    = 0,
+    LED_GREEN  = 1,
+    LED_RED    = 2,
+    LED_YELLOW = 3,
+    LED_BLINK_YELLOW = 4,
+    LED_BLINK_GREEN = 5,
+    LED_BLINK_RED_YELLOW = 6
+} freenect_led_options;
+
+typedef enum {	  
+	FREENECT_FORMAT_11_BIT = 0,
+	FREENECT_FORMAT_10_BIT = 1
+} freenect_depth_format;
+
+struct _freenect_context;
+typedef struct _freenect_context freenect_context;
+
+struct _freenect_device;
+typedef struct _freenect_device freenect_device;
+
+// usb backend specific section
+#include <libusb.h>
+typedef libusb_context freenect_usb_context;
+//
+
+int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx);
+int freenect_shutdown(freenect_context *ctx);
+
+int freenect_process_events(freenect_context *ctx);
+
+int freenect_num_devices(freenect_context *ctx);
+int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index);
+int freenect_close_device(freenect_device *dev);
+
+void freenect_set_user(freenect_device *dev, void *user);
+void *freenect_get_user(freenect_device *dev);
+
+typedef void (*freenect_depth_cb)(freenect_device *dev, freenect_depth *depth, uint32_t timestamp);
+typedef void (*freenect_rgb_cb)(freenect_device *dev, freenect_pixel *rgb, uint32_t timestamp);
+
+void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb);
+void freenect_set_rgb_callback(freenect_device *dev, freenect_rgb_cb cb);
+int freenect_set_rgb_format(freenect_device *dev, freenect_rgb_format fmt);
+int freenect_set_depth_format(freenect_device *dev, freenect_depth_format fmt);
+
+int freenect_start_depth(freenect_device *dev);
+int freenect_start_rgb(freenect_device *dev);
+int freenect_stop_depth(freenect_device *dev);
+int freenect_stop_rgb(freenect_device *dev);
+
+
+int freenect_set_tilt_in_degrees(freenect_device *dev, double angle);
+int freenect_set_tilt_in_radians(freenect_device *dev, double angle);
+int freenect_set_led(freenect_device *dev, freenect_led_options option);
+
+int freenect_get_raw_accelerometers(freenect_device *dev, int16_t* x, int16_t* y, int16_t* z);
+int freenect_get_mks_accelerometers(freenect_device *dev, double* x, double* y, double* z);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //
+

driver/libfreenect/usb_libusb10.c

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <libusb.h>
+#include "freenect_internal.h"
+
+int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx)
+{
+	int res;
+	if (!usb_ctx) {
+		res = libusb_init(&ctx->ctx);
+		if (res >= 0) {
+			ctx->should_free_ctx = 1;
+			return 0;
+		} else {
+			ctx->should_free_ctx = 0;
+			ctx->ctx = NULL;
+			return res;
+		}
+	} else {
+		ctx->ctx = usb_ctx;
+		ctx->should_free_ctx = 0;
+		return 0;
+	}
+}
+
+int fnusb_shutdown(fnusb_ctx *ctx)
+{
+	//int res;
+	if (ctx->should_free_ctx) {
+		libusb_exit(ctx->ctx);
+		ctx->ctx = NULL;
+	}
+	return 0;
+}
+
+int fnusb_process_events(fnusb_ctx *ctx)
+{
+	return libusb_handle_events(ctx->ctx);
+}
+
+int fnusb_open_subdevices(freenect_device *dev, int index)
+{
+	dev->usb_cam.parent = dev;
+
+	// Search for 0x45e (Microsoft Corp.) and 0x02ae
+	//dev->usb_cam.dev = libusb_open_device_with_vid_pid(dev->parent->usb.ctx, 0x45e, 0x2ae);
+
+	libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
+	ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices
+	if (cnt < 0)
+		return (-1);
+
+	bool start_cam = false, start_motor = false;
+
+	int i = 0, nr_cam = 0, nr_mot = 0;
+	struct libusb_device_descriptor desc;
+	for (i = 0; i < cnt; ++i)
+	{
+		int r = libusb_get_device_descriptor (devs[i], &desc);
+		if (r < 0)
+			continue;
+
+		// Search for the camera
+		if (desc.idVendor == MS_MAGIC_VENDOR && desc.idProduct == MS_MAGIC_CAMERA_PRODUCT && !start_cam)
+		{
+			// If the index given by the user matches our camera index
+			if (nr_cam == index)
+			{
+				if (libusb_open (devs[i], &dev->usb_cam.dev) != 0)
+					return (-1);
+				// Claim the camera
+				if (!dev->usb_cam.dev) 
+					return (-1);
+				libusb_claim_interface (dev->usb_cam.dev, 0);
+				start_cam = true;
+			}
+			else
+				nr_cam++;
+		}
+
+		// Search for the motor
+		if (desc.idVendor == MS_MAGIC_VENDOR && desc.idProduct == MS_MAGIC_MOTOR_PRODUCT && !start_motor)
+		{
+			// If the index given by the user matches our camera index
+			if (nr_mot == index)
+			{
+				//libusb_open_device_with_vid_pid (dev->parent->usb.ctx, MS_MAGIC_VENDOR, MS_MAGIC_MOTOR_PRODUCT);
+				if (libusb_open (devs[i], &dev->usb_motor.dev) != 0)
+					return (-1);
+				// Claim the motor
+				if (!dev->usb_motor.dev)
+					return (-1);
+				libusb_claim_interface (dev->usb_motor.dev, 0);
+				start_motor = true;
+			}
+			else
+				nr_mot++;
+		}
+	}
+
+	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it
+
+	if (start_cam && start_motor)
+		return (0);
+	else
+		return (-1);
+}
+
+static void iso_callback(struct libusb_transfer *xfer)
+{
+	int i;
+	fnusb_isoc_stream *strm = xfer->user_data;
+
+	if(xfer->status == LIBUSB_TRANSFER_COMPLETED) {
+		uint8_t *buf = (void*)xfer->buffer;
+		for (i=0; i<strm->pkts; i++) {
+			strm->cb(strm->parent->parent, buf, xfer->iso_packet_desc[i].actual_length);
+			buf += strm->len;
+		}
+		libusb_submit_transfer(xfer);
+	} else {
+		printf("Xfer error: %d\n", xfer->status);
+	}
+}
+
+int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len)
+{
+	int ret, i;
+
+	strm->parent = dev;
+	strm->cb = cb;
+	strm->num_xfers = xfers;
+	strm->pkts = pkts;
+	strm->len = len;
+	strm->buffer = malloc(xfers * pkts * len);
+	strm->xfers = malloc(sizeof(struct libusb_transfer*) * xfers);
+
+	uint8_t *bufp = strm->buffer;
+
+	for (i=0; i<xfers; i++) {
+		//printf("Creating EP %02x transfer #%d\n", ep, i);
+		strm->xfers[i] = libusb_alloc_transfer(pkts);
+
+		libusb_fill_iso_transfer(strm->xfers[i], dev->dev, ep, bufp, pkts * len, pkts, iso_callback, strm, 0);
+
+		libusb_set_iso_packet_lengths(strm->xfers[i], len);
+
+		ret = libusb_submit_transfer(strm->xfers[i]);
+		if (ret < 0)
+			printf("Failed to submit xfer %d: %d\n", i, ret);
+
+		bufp += pkts*len;
+	}
+
+	return 0;
+
+}
+
+int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength)
+{
+	return libusb_control_transfer(dev->dev, bmRequestType, bRequest, wValue, wIndex, data, wLength, 0);
+}

driver/libfreenect/usb_libusb10.h

+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ *   1) Leave this header intact and distribute it under the same terms,
+ *      accompanying it with the APACHE20 and GPL20 files, or
+ *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#ifndef USB_LIBUSB10
+#define USB_LIBUSB10
+
+#include <libusb.h>
+
+#if defined(__APPLE__)
+/*
+  From Github Issue 22 by Roefer -
+  https://github.com/OpenKinect/libfreenect/issues/#issue/22
+
+  The current implementation still does not reach 30 Hz on MacOS. This
+  is due to bad scheduling of USB transfers in libusb (Ed Note: libusb
+  1.0.8). A fix can be found at
+  http://www.informatik.uni-bremen.de/~roefer/libusb/libusb-osx-kinect.diff
+
+  (Ed Note: patch applies to libusb repo at 7da756e09fd)
+
+  In camera.c, I use PKTS_PER_XFER = 128, NUM_XFERS = 4. There are a
+  few rules: PKTS_PER_XFER * NUM_XFERS <= 1000, PKTS_PER_XFER % 8 == 0.
+*/
+#define PKTS_PER_XFER 128
+#define NUM_XFERS 4
+#define DEPTH_PKTBUF 2048
+#define RGB_PKTBUF 2048
+#else
+#define PKTS_PER_XFER 16
+#define NUM_XFERS 16
+#define DEPTH_PKTBUF 1920
+#define RGB_PKTBUF 1920
+#endif
+
+
+typedef struct {
+	libusb_context *ctx;
+	int should_free_ctx;
+} fnusb_ctx;
+
+typedef struct {
+	freenect_device *parent; //so we can go up from the libusb userdata
+	libusb_device_handle *dev;
+} fnusb_dev;
+
+typedef struct {
+	fnusb_dev *parent; //so we can go up from the libusb userdata
+	struct libusb_transfer **xfers;
+	uint8_t *buffer;
+	fnusb_iso_cb cb;
+	int num_xfers;
+	int pkts;
+	int len;
+} fnusb_isoc_stream;
+
+int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx);
+int fnusb_shutdown(fnusb_ctx *ctx);
+int fnusb_process_events(fnusb_ctx *ctx);
+
+int fnusb_open_subdevices(freenect_device *dev, int index);
+
+int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len);
+int fnusb_stop_iso(fnusb_dev *dev, fnusb_isoc_stream *strm);
+
+int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength);
+
+
+#endif

driver/libusb/libusb.h

+/*
+ * Public libusb header file
+ * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __LIBUSB_H__
+#define __LIBUSB_H__
+
+/* MSVC doesn't like inline, but does accept __inline ?? */
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+#include <limits.h>
+
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__)
+#include <sys/time.h>
+#endif
+
+/* 'interface' might be defined as a macro on Windows, so we need to
+ * undefine it so as not to break the current libusb API, because
+ * libusb_config_descriptor has an 'interface' member
+ * As this can be problematic if you include windows.h after libusb.h
+ * in your sources, we force windows.h to be included first. */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#include <windows.h>
+#if defined(interface)
+#undef interface
+#endif
+#endif
+
+/** \def LIBUSB_CALL
+ * \ingroup misc
+ * libusb's Windows calling convention.
+ *
+ * Under Windows, the selection of available compilers and configurations
+ * means that, unlike other platforms, there is not <em>one true calling
+ * convention</em> (calling convention: the manner in which parameters are
+ * passed to funcions in the generated assembly code).
+ *
+ * Matching the Windows API itself, libusb uses the WINAPI convention (which
+ * translates to the <tt>stdcall</tt> convention) and guarantees that the
+ * library is compiled in this way. The public header file also includes
+ * appropriate annotations so that your own software will use the right
+ * convention, even if another convention is being used by default within
+ * your codebase.
+ *
+ * The one consideration that you must apply in your software is to mark
+ * all functions which you use as libusb callbacks with this LIBUSB_CALL
+ * annotation, so that they too get compiled for the correct calling
+ * convention.
+ *
+ * On non-Windows operating systems, this macro is defined as nothing. This
+ * means that you can apply it to your code without worrying about
+ * cross-platform compatibility.
+ */
+/* LIBUSB_CALL must be defined on both definition and declaration of libusb
+ * functions. You'd think that declaration would be enough, but cygwin will
+ * complain about conflicting types unless both are marked this way.
+ * The placement of this macro is important too; it must appear after the
+ * return type, before the function name. See internal documentation for
+ * API_EXPORTED.
+ */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define LIBUSB_CALL WINAPI
+#else
+#define LIBUSB_CALL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \def libusb_cpu_to_le16
+ * \ingroup misc
+ * Convert a 16-bit value from host-endian to little-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the host-endian value to convert
+ * \returns the value in little-endian byte order
+ */
+static inline uint16_t libusb_cpu_to_le16(const uint16_t x)
+{
+	union {
+		uint8_t  b8[2];
+		uint16_t b16;
+	} _tmp;
+	_tmp.b8[1] = x >> 8;
+	_tmp.b8[0] = x & 0xff;
+	return _tmp.b16;
+}
+
+/** \def libusb_le16_to_cpu
+ * \ingroup misc
+ * Convert a 16-bit value from little-endian to host-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the little-endian value to convert
+ * \returns the value in host-endian byte order
+ */
+#define libusb_le16_to_cpu libusb_cpu_to_le16
+
+/* standard USB stuff */
+
+/** \ingroup desc
+ * Device and/or Interface Class codes */
+enum libusb_class_code {
+	/** In the context of a \ref libusb_device_descriptor "device descriptor",
+	 * this bDeviceClass value indicates that each interface specifies its
+	 * own class information and all interfaces operate independently.
+	 */
+	LIBUSB_CLASS_PER_INTERFACE = 0,
+
+	/** Audio class */
+	LIBUSB_CLASS_AUDIO = 1,
+
+	/** Communications class */
+	LIBUSB_CLASS_COMM = 2,
+
+	/** Human Interface Device class */
+	LIBUSB_CLASS_HID = 3,
+
+	/** Printer dclass */
+	LIBUSB_CLASS_PRINTER = 7,
+
+	/** Picture transfer protocol class */
+	LIBUSB_CLASS_PTP = 6,
+
+	/** Mass storage class */
+	LIBUSB_CLASS_MASS_STORAGE = 8,
+
+	/** Hub class */
+	LIBUSB_CLASS_HUB = 9,
+
+	/** Data class */
+	LIBUSB_CLASS_DATA = 10,
+
+	/** Wireless class */
+	LIBUSB_CLASS_WIRELESS = 0xe0,
+
+	/** Application class */
+	LIBUSB_CLASS_APPLICATION = 0xfe,
+
+	/** Class is vendor-specific */
+	LIBUSB_CLASS_VENDOR_SPEC = 0xff
+};
+
+/** \ingroup desc
+ * Descriptor types as defined by the USB specification. */
+enum libusb_descriptor_type {
+	/** Device descriptor. See libusb_device_descriptor. */
+	LIBUSB_DT_DEVICE = 0x01,
+
+	/** Configuration descriptor. See libusb_config_descriptor. */
+	LIBUSB_DT_CONFIG = 0x02,
+
+	/** String descriptor */
+	LIBUSB_DT_STRING = 0x03,
+
+	/** Interface descriptor. See libusb_interface_descriptor. */
+	LIBUSB_DT_INTERFACE = 0x04,
+
+	/** Endpoint descriptor. See libusb_endpoint_descriptor. */
+	LIBUSB_DT_ENDPOINT = 0x05,
+
+	/** HID descriptor */
+	LIBUSB_DT_HID = 0x21,
+
+	/** HID report descriptor */
+	LIBUSB_DT_REPORT = 0x22,
+
+	/** Physical descriptor */
+	LIBUSB_DT_PHYSICAL = 0x23,
+
+	/** Hub descriptor */
+	LIBUSB_DT_HUB = 0x29
+};
+
+/* Descriptor sizes per descriptor type */
+#define LIBUSB_DT_DEVICE_SIZE			18
+#define LIBUSB_DT_CONFIG_SIZE			9
+#define LIBUSB_DT_INTERFACE_SIZE		9
+#define LIBUSB_DT_ENDPOINT_SIZE		7
+#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
+#define LIBUSB_DT_HUB_NONVAR_SIZE		7
+
+#define LIBUSB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */
+#define LIBUSB_ENDPOINT_DIR_MASK		0x80
+
+/** \ingroup desc
+ * Endpoint direction. Values for bit 7 of the
+ * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme.
+ */
+enum libusb_endpoint_direction {
+	/** In: device-to-host */
+	LIBUSB_ENDPOINT_IN = 0x80,
+
+	/** Out: host-to-device */
+	LIBUSB_ENDPOINT_OUT = 0x00
+};
+
+#define LIBUSB_TRANSFER_TYPE_MASK			0x03    /* in bmAttributes */
+
+/** \ingroup desc
+ * Endpoint transfer type. Values for bits 0:1 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field.
+ */
+enum libusb_transfer_type {
+	/** Control endpoint */
+	LIBUSB_TRANSFER_TYPE_CONTROL = 0,
+
+	/** Isochronous endpoint */
+	LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,
+
+	/** Bulk endpoint */
+	LIBUSB_TRANSFER_TYPE_BULK = 2,
+
+	/** Interrupt endpoint */
+	LIBUSB_TRANSFER_TYPE_INTERRUPT = 3
+};
+
+/** \ingroup misc
+ * Standard requests, as defined in table 9-3 of the USB2 specifications */
+enum libusb_standard_request {
+	/** Request status of the specific recipient */
+	LIBUSB_REQUEST_GET_STATUS = 0x00,
+
+	/** Clear or disable a specific feature */
+	LIBUSB_REQUEST_CLEAR_FEATURE = 0x01,
+
+	/* 0x02 is reserved */
+
+	/** Set or enable a specific feature */
+	LIBUSB_REQUEST_SET_FEATURE = 0x03,
+
+	/* 0x04 is reserved */
+
+	/** Set device address for all future accesses */
+	LIBUSB_REQUEST_SET_ADDRESS = 0x05,
+
+	/** Get the specified descriptor */
+	LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06,
+
+	/** Used to update existing descriptors or add new descriptors */
+	LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07,
+
+	/** Get the current device configuration value */
+	LIBUSB_REQUEST_GET_CONFIGURATION = 0x08,
+
+	/** Set device configuration */
+	LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,
+
+	/** Return the selected alternate setting for the specified interface */
+	LIBUSB_REQUEST_GET_INTERFACE = 0x0A,
+
+	/** Select an alternate interface for the specified interface */
+	LIBUSB_REQUEST_SET_INTERFACE = 0x0B,
+
+	/** Set then report an endpoint's synchronization frame */
+	LIBUSB_REQUEST_SYNCH_FRAME = 0x0C
+};
+
+/** \ingroup misc
+ * Request type bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. */
+enum libusb_request_type {
+	/** Standard */
+	LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),
+
+	/** Class */
+	LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5),
+
+	/** Vendor */
+	LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),
+
+	/** Reserved */
+	LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5)
+};
+
+/** \ingroup misc
+ * Recipient bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. Values 4 through 31 are reserved. */
+enum libusb_request_recipient {
+	/** Device */
+	LIBUSB_RECIPIENT_DEVICE = 0x00,
+
+	/** Interface */
+	LIBUSB_RECIPIENT_INTERFACE = 0x01,
+
+	/** Endpoint */
+	LIBUSB_RECIPIENT_ENDPOINT = 0x02,
+
+	/** Other */
+	LIBUSB_RECIPIENT_OTHER = 0x03
+};
+
+#define LIBUSB_ISO_SYNC_TYPE_MASK		0x0C
+
+/** \ingroup desc
+ * Synchronization type for isochronous endpoints. Values for bits 2:3 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_sync_type {
+	/** No synchronization */
+	LIBUSB_ISO_SYNC_TYPE_NONE = 0,
+
+	/** Asynchronous */
+	LIBUSB_ISO_SYNC_TYPE_ASYNC = 1,
+
+	/** Adaptive */
+	LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2,
+
+	/** Synchronous */
+	LIBUSB_ISO_SYNC_TYPE_SYNC = 3
+};
+
+#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30
+
+/** \ingroup desc
+ * Usage type for isochronous endpoints. Values for bits 4:5 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_usage_type {
+	/** Data endpoint */
+	LIBUSB_ISO_USAGE_TYPE_DATA = 0,
+
+	/** Feedback endpoint */
+	LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1,
+
+	/** Implicit feedback Data endpoint */
+	LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB device descriptor. This
+ * descriptor is documented in section 9.6.1 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_device_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
+	 * context. */
+	uint8_t  bDescriptorType;
+
+	/** USB specification release number in binary-coded decimal. A value of
+	 * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
+	uint16_t bcdUSB;
+
+	/** USB-IF class code for the device. See \ref libusb_class_code. */
+	uint8_t  bDeviceClass;
+
+	/** USB-IF subclass code for the device, qualified by the bDeviceClass
+	 * value */
+	uint8_t  bDeviceSubClass;
+
+	/** USB-IF protocol code for the device, qualified by the bDeviceClass and
+	 * bDeviceSubClass values */
+	uint8_t  bDeviceProtocol;
+
+	/** Maximum packet size for endpoint 0 */
+	uint8_t  bMaxPacketSize0;
+
+	/** USB-IF vendor ID */
+	uint16_t idVendor;
+
+	/** USB-IF product ID */
+	uint16_t idProduct;
+
+	/** Device release number in binary-coded decimal */
+	uint16_t bcdDevice;
+
+	/** Index of string descriptor describing manufacturer */
+	uint8_t  iManufacturer;
+
+	/** Index of string descriptor describing product */
+	uint8_t  iProduct;
+
+	/** Index of string descriptor containing device serial number */
+	uint8_t  iSerialNumber;
+
+	/** Number of possible configurations */
+	uint8_t  bNumConfigurations;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB endpoint descriptor. This
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_endpoint_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in
+	 * this context. */
+	uint8_t  bDescriptorType;
+
+	/** The address of the endpoint described by this descriptor. Bits 0:3 are
+	 * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction,
+	 * see \ref libusb_endpoint_direction.
+	 */
+	uint8_t  bEndpointAddress;
+
+	/** Attributes which apply to the endpoint when it is configured using
+	 * the bConfigurationValue. Bits 0:1 determine the transfer type and
+	 * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for
+	 * isochronous endpoints and correspond to \ref libusb_iso_sync_type.
+	 * Bits 4:5 are also only used for isochronous endpoints and correspond to
+	 * \ref libusb_iso_usage_type. Bits 6:7 are reserved.
+	 */
+	uint8_t  bmAttributes;
+
+	/** Maximum packet size this endpoint is capable of sending/receiving. */
+	uint16_t wMaxPacketSize;
+
+	/** Interval for polling endpoint for data transfers. */
+	uint8_t  bInterval;
+
+	/** For audio devices only: the rate at which synchronization feedback
+	 * is provided. */
+	uint8_t  bRefresh;
+
+	/** For audio devices only: the address if the synch endpoint */
+	uint8_t  bSynchAddress;
+
+	/** Extra descriptors. If libusb encounters unknown endpoint descriptors,
+	 * it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB interface descriptor. This
+ * descriptor is documented in section 9.6.5 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_interface_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE
+	 * in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Number of this interface */
+	uint8_t  bInterfaceNumber;
+
+	/** Value used to select this alternate setting for this interface */
+	uint8_t  bAlternateSetting;
+
+	/** Number of endpoints used by this interface (excluding the control
+	 * endpoint). */
+	uint8_t  bNumEndpoints;
+
+	/** USB-IF class code for this interface. See \ref libusb_class_code. */
+	uint8_t  bInterfaceClass;
+
+	/** USB-IF subclass code for this interface, qualified by the
+	 * bInterfaceClass value */
+	uint8_t  bInterfaceSubClass;
+
+	/** USB-IF protocol code for this interface, qualified by the
+	 * bInterfaceClass and bInterfaceSubClass values */
+	uint8_t  bInterfaceProtocol;
+
+	/** Index of string descriptor describing this interface */
+	uint8_t  iInterface;
+
+	/** Array of endpoint descriptors. This length of this array is determined
+	 * by the bNumEndpoints field. */
+	const struct libusb_endpoint_descriptor *endpoint;
+
+	/** Extra descriptors. If libusb encounters unknown interface descriptors,
+	 * it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup desc
+ * A collection of alternate settings for a particular USB interface.
+ */
+struct libusb_interface {
+	/** Array of interface descriptors. The length of this array is determined
+	 * by the num_altsetting field. */
+	const struct libusb_interface_descriptor *altsetting;
+
+	/** The number of alternate settings that belong to this interface */
+	int num_altsetting;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB configuration descriptor. This
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_config_descriptor {
+	/** Size of this descriptor (in bytes) */
+	uint8_t  bLength;
+
+	/** Descriptor type. Will have value
+	 * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG
+	 * in this context. */
+	uint8_t  bDescriptorType;
+
+	/** Total length of data returned for this configuration */
+	uint16_t wTotalLength;
+
+	/** Number of interfaces supported by this configuration */
+	uint8_t  bNumInterfaces;
+
+	/** Identifier value for this configuration */
+	uint8_t  bConfigurationValue;
+
+	/** Index of string descriptor describing this configuration */
+	uint8_t  iConfiguration;
+
+	/** Configuration characteristics */
+	uint8_t  bmAttributes;
+
+	/** Maximum power consumption of the USB device from this bus in this
+	 * configuration when the device is fully opreation. Expressed in units
+	 * of 2 mA. */
+	uint8_t  MaxPower;
+
+	/** Array of interfaces supported by this configuration. The length of
+	 * this array is determined by the bNumInterfaces field. */
+	const struct libusb_interface *interface;
+
+	/** Extra descriptors. If libusb encounters unknown configuration
+	 * descriptors, it will store them here, should you wish to parse them. */
+	const unsigned char *extra;
+
+	/** Length of the extra descriptors, in bytes. */
+	int extra_length;
+};
+
+/** \ingroup asyncio
+ * Setup packet for control transfers. */
+struct libusb_control_setup {
+	/** Request type. Bits 0:4 determine recipient, see
+	 * \ref libusb_request_recipient. Bits 5:6 determine type, see
+	 * \ref libusb_request_type. Bit 7 determines data transfer direction, see
+	 * \ref libusb_endpoint_direction.
+	 */
+	uint8_t  bmRequestType;
+
+	/** Request. If the type bits of bmRequestType are equal to
+	 * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
+	 * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to
+	 * \ref libusb_standard_request. For other cases, use of this field is
+	 * application-specific. */
+	uint8_t  bRequest;
+
+	/** Value. Varies according to request */
+	uint16_t wValue;
+
+	/** Index. Varies according to request, typically used to pass an index
+	 * or offset */
+	uint16_t wIndex;
+
+	/** Number of bytes to transfer */
+	uint16_t wLength;
+};
+
+#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup))
+
+/* libusb */
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_device_handle;
+
+/** \ingroup lib
+ * Structure representing a libusb session. The concept of individual libusb
+ * sessions allows for your program to use two libraries (or dynamically
+ * load two modules) which both independently use libusb. This will prevent
+ * interference between the individual libusb users - for example
+ * libusb_set_debug() will not affect the other user of the library, and
+ * libusb_exit() will not destroy resources that the other user is still
+ * using.
+ *
+ * Sessions are created by libusb_init() and destroyed through libusb_exit().
+ * If your application is guaranteed to only ever include a single libusb
+ * user (i.e. you), you do not have to worry about contexts: pass NULL in
+ * every function call where a context is required. The default context
+ * will be used.
+ *
+ * For more information, see \ref contexts.
+ */
+typedef struct libusb_context libusb_context;
+
+/** \ingroup dev
+ * Structure representing a USB device detected on the system. This is an
+ * opaque type for which you are only ever provided with a pointer, usually
+ * originating from libusb_get_device_list().
+ *
+ * Certain operations can be performed on a device, but in order to do any
+ * I/O you will have to first obtain a device handle using libusb_open().
+ *
+ * Devices are reference counted with libusb_device_ref() and
+ * libusb_device_unref(), and are freed when the reference count reaches 0.
+ * New devices presented by libusb_get_device_list() have a reference count of
+ * 1, and libusb_free_device_list() can optionally decrease the reference count
+ * on all devices in the list. libusb_open() adds another reference which is
+ * later destroyed by libusb_close().
+ */
+typedef struct libusb_device libusb_device;
+
+
+/** \ingroup dev
+ * Structure representing a handle on a USB device. This is an opaque type for
+ * which you are only ever provided with a pointer, usually originating from
+ * libusb_open().
+ *
+ * A device handle is used to perform I/O and other operations. When finished
+ * with a device handle, you should call libusb_close().
+ */
+typedef struct libusb_device_handle libusb_device_handle;
+
+/** \ingroup misc
+ * Error codes. Most libusb functions return 0 on success or one of these
+ * codes on failure.
+ * You can use libusb_strerror() to retrieve a short string description of
+ * a libusb_error enumeration value.
+ */
+enum libusb_error {
+	/** Success (no error) */
+	LIBUSB_SUCCESS = 0,
+
+	/** Input/output error */
+	LIBUSB_ERROR_IO = -1,
+
+	/** Invalid parameter */
+	LIBUSB_ERROR_INVALID_PARAM = -2,
+
+	/** Access denied (insufficient permissions) */
+	LIBUSB_ERROR_ACCESS = -3,
+
+	/** No such device (it may have been disconnected) */
+	LIBUSB_ERROR_NO_DEVICE = -4,
+
+	/** Entity not found */
+	LIBUSB_ERROR_NOT_FOUND = -5,
+
+	/** Resource busy */
+	LIBUSB_ERROR_BUSY = -6,
+
+	/** Operation timed out */
+	LIBUSB_ERROR_TIMEOUT = -7,
+
+	/** Overflow */
+	LIBUSB_ERROR_OVERFLOW = -8,
+
+	/** Pipe error */
+	LIBUSB_ERROR_PIPE = -9,
+
+	/** System call interrupted (perhaps due to signal) */
+	LIBUSB_ERROR_INTERRUPTED = -10,
+
+	/** Insufficient memory */
+	LIBUSB_ERROR_NO_MEM = -11,
+
+	/** Operation not supported or unimplemented on this platform */
+	LIBUSB_ERROR_NOT_SUPPORTED = -12,
+
+	/** Other error */
+	LIBUSB_ERROR_OTHER = -99
+
+	/* IMPORTANT: when adding new values to this enum, remember to
+	   update the libusb_strerror() function implementation! */
+};
+
+/** \ingroup asyncio
+ * Transfer status codes */
+enum libusb_transfer_status {
+	/** Transfer completed without error. Note that this does not indicate
+	 * that the entire amount of requested data was transferred. */
+	LIBUSB_TRANSFER_COMPLETED,
+
+	/** Transfer failed */
+	LIBUSB_TRANSFER_ERROR,
+
+	/** Transfer timed out */