From 4743a6e02936f7378b4b7b047c75760e93a8646d Mon Sep 17 00:00:00 2001 From: Joakim Gebart Date: Tue, 24 Jan 2012 14:49:09 +0100 Subject: [PATCH 01/10] C++ wrapper: ignore LIBUSB_ERROR_INTERRUPTED from freenect_process_events() I kept getting errors about "Cannot process freenect events" when trying to start cppview although glview worked perfectly. It turns out libusb kept returning error "interrupted" when starting up, this patch ignores all such errors from libusb. I do not know libusb well enough to be able to tell whether this workaround will cause any problems in special cases. cppview seems to be working, but crashes when pressing ESC or closing the window with the error "pure virtual method called". I'm still investigating that error but I do not think it is related to this patch. Signed-off-by: Joakim Gebart --- wrappers/cpp/libfreenect.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/wrappers/cpp/libfreenect.hpp b/wrappers/cpp/libfreenect.hpp index 0a5f637e..b5ecdf16 100644 --- a/wrappers/cpp/libfreenect.hpp +++ b/wrappers/cpp/libfreenect.hpp @@ -28,8 +28,10 @@ #include #include +#include #include #include +#include namespace Freenect { class Noncopyable { @@ -209,7 +211,20 @@ namespace Freenect { // Do not call directly, thread runs here void operator()() { while(!m_stop) { - if(freenect_process_events(m_ctx) < 0) throw std::runtime_error("Cannot process freenect events"); + int res = freenect_process_events(m_ctx); + if (res < 0) + { + // libusb signals an error has occurred + if (res == LIBUSB_ERROR_INTERRUPTED) + { + // This happens sometimes, it means that a system call in libusb was interrupted somehow (perhaps due to a signal) + // The simple solution seems to be just ignore it. + continue; + } + std::stringstream ss; + ss << "Cannot process freenect events (libusb error code: " << res << ")"; + throw std::runtime_error(ss.str()); + } } } static void *pthread_callback(void *user_data) { From 9807cfea158110eca04ac0fb98cede8fbea589c6 Mon Sep 17 00:00:00 2001 From: Drew Fisher Date: Thu, 22 Mar 2012 12:29:02 -0700 Subject: [PATCH 02/10] freenect.pyx: add FREENECT_DEPTH_{MM,REGISTERED} support Signed-off-by: Drew Fisher --- wrappers/python/freenect.pyx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wrappers/python/freenect.pyx b/wrappers/python/freenect.pyx index c76ba301..162561f5 100644 --- a/wrappers/python/freenect.pyx +++ b/wrappers/python/freenect.pyx @@ -49,6 +49,8 @@ cdef extern from "libfreenect.h": FREENECT_DEPTH_10BIT FREENECT_DEPTH_11BIT_PACKED FREENECT_DEPTH_10BIT_PACKED + FREENECT_DEPTH_REGISTERED + FREENECT_DEPTH_MM ctypedef enum freenect_led_options: FREENECT_LED_OFF "LED_OFF" @@ -148,6 +150,8 @@ DEPTH_11BIT = FREENECT_DEPTH_11BIT DEPTH_10BIT = FREENECT_DEPTH_10BIT DEPTH_11BIT_PACKED = FREENECT_DEPTH_11BIT_PACKED DEPTH_10BIT_PACKED = FREENECT_DEPTH_10BIT_PACKED +DEPTH_REGISTERED = FREENECT_DEPTH_REGISTERED +DEPTH_MM = FREENECT_DEPTH_MM LED_OFF = FREENECT_LED_OFF LED_GREEN = FREENECT_LED_GREEN LED_RED = FREENECT_LED_RED @@ -476,7 +480,7 @@ def sync_get_depth(index=0, format=DEPTH_11BIT): if out: error_open_device() return - if format == DEPTH_11BIT: + if format in [DEPTH_11BIT, DEPTH_10BIT, DEPTH_MM, DEPTH_REGISTERED]: dims[0], dims[1] = 480, 640 return PyArray_SimpleNewFromData(2, dims, npc.NPY_UINT16, data), timestamp else: From 8160ddd1fa524423e141a52f73047007d7ac23d5 Mon Sep 17 00:00:00 2001 From: Drew Fisher Date: Sat, 24 Mar 2012 18:31:13 -0700 Subject: [PATCH 03/10] audio firmware loader: use the structure of the firmware image format to specify size/addresses Signed-off-by: Drew Fisher --- src/loader.c | 39 +++++++++++++++++++++++++++++++++++---- src/loader.h | 11 +++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/loader.c b/src/loader.c index f5bf0585..0451b1fb 100644 --- a/src/loader.c +++ b/src/loader.c @@ -193,11 +193,37 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) { return -errno; } // Now we have an open firmware file handle. - uint32_t addr = 0x00080000; - int read; + firmware_header fwheader; + int read = 0; + read = fread(&fwheader, 1, sizeof(firmware_header), fw); + if (read != sizeof(firmware_header)) { + FN_ERROR("upload_firmware: firmware image too small, has no header?\n"); + fclose(fw); + return -errno; + } + // The file is serialized as little endian. + fwheader.magic = fn_le32(fwheader.magic); + fwheader.ver_major = fn_le16(fwheader.ver_major); + fwheader.ver_minor = fn_le16(fwheader.ver_minor); + fwheader.ver_release = fn_le16(fwheader.ver_release); + fwheader.ver_patch = fn_le16(fwheader.ver_patch); + fwheader.base_addr = fn_le32(fwheader.base_addr); + fwheader.size = fn_le32(fwheader.size); + fwheader.entry_addr = fn_le32(fwheader.entry_addr); + FN_INFO("Found firmware image:\n"); + FN_INFO("\tmagic %08X\n", fwheader.magic); + FN_INFO("\tversion %02d.%02d.%02d.%02d\n", fwheader.ver_major, fwheader.ver_minor, fwheader.ver_release, fwheader.ver_patch); + FN_INFO("\tbase address 0x%08x\n", fwheader.base_addr); + FN_INFO("\tsize 0x%08x\n", fwheader.size); + FN_INFO("\tentry point 0x%08x\n", fwheader.entry_addr); + + rewind(fw); + uint32_t addr = fwheader.base_addr; unsigned char page[0x4000]; + int total_bytes_sent = 0; do { - read = fread(page, 1, 0x4000, fw); + size_t block_size = (0x4000 > fwheader.size - total_bytes_sent) ? fwheader.size - total_bytes_sent : 0x4000; + read = fread(page, 1, block_size, fw); if(read <= 0) { break; } @@ -224,6 +250,7 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) { return -1; } bytes_sent += to_send; + total_bytes_sent += to_send; } res = get_reply(dev); addr += (uint32_t)read; @@ -231,11 +258,15 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) { } while (read > 0); fclose(fw); fw = NULL; + if (total_bytes_sent != fwheader.size) { + FN_ERROR("upload_firmware: firmware image declared %d bytes, but file only contained %d bytes\n", fwheader.size, total_bytes_sent); + return -1; + } bootcmd.tag = fn_le32(dev->parent->audio_tag); bootcmd.bytes = fn_le32(0); bootcmd.cmd = fn_le32(0x04); - bootcmd.addr = fn_le32(0x00080030); + bootcmd.addr = fn_le32(fwheader.entry_addr); dump_bl_cmd(ctx, bootcmd); res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred); if(res != 0 || transferred != sizeof(bootcmd)) { diff --git a/src/loader.h b/src/loader.h index 82782205..dcec08aa 100644 --- a/src/loader.h +++ b/src/loader.h @@ -39,6 +39,17 @@ typedef struct { uint32_t unk; } bootloader_command; +typedef struct { + uint32_t magic; // Magic bytes. 2BL uses 0xF00BACCA, audios uses 0xCA77F00D + uint16_t ver_minor; // The version string has four parts, each a 16-bit little-endian int. + uint16_t ver_major; // Yes, minor comes before major. + uint16_t ver_release; // + uint16_t ver_patch; // + uint32_t base_addr; // Base address of firmware image. 2BL starts at 0x10000, audios starts at 0x80000. + uint32_t size; // Size of firmware image, in bytes + uint32_t entry_addr; // Code entry point (absolute address) +} firmware_header; + typedef struct { uint32_t magic; uint32_t tag; From 6140a46d06c9600b2b0ed52febdbe7b7b91625fa Mon Sep 17 00:00:00 2001 From: Drew Fisher Date: Sat, 24 Mar 2012 18:34:06 -0700 Subject: [PATCH 04/10] wavrecord.c: initialize sample count to 0 Signed-off-by: Drew Fisher --- examples/wavrecord.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/wavrecord.c b/examples/wavrecord.c index c7abc697..655b39ef 100644 --- a/examples/wavrecord.c +++ b/examples/wavrecord.c @@ -93,6 +93,7 @@ int main(int argc, char** argv) { } capture state; + state.samples = 0; state.logfiles[0] = fopen("channel1.wav", "wb"); state.logfiles[1] = fopen("channel2.wav", "wb"); state.logfiles[2] = fopen("channel3.wav", "wb"); From 16afaf845eabb75c9dd4c0d77ed3330f85027af6 Mon Sep 17 00:00:00 2001 From: Drew Fisher Date: Thu, 29 Mar 2012 11:55:04 -0700 Subject: [PATCH 05/10] examples: GLUT_INCLUDE_DIRS -> GLUT_INCLUDE_DIR We had misspelled the environment variable in CMakeLists.txt. Reported by Ski-lleR on github. Signed-off-by: Drew Fisher --- examples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 examples/CMakeLists.txt diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt old mode 100755 new mode 100644 index 13c98fc4..506ca9bd --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -56,7 +56,7 @@ else() find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) - include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} ${USB_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) target_link_libraries(glview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(regview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) From 1ddb0faeb6bc6deae50b0f098ae8005a0e403597 Mon Sep 17 00:00:00 2001 From: Benn Snyder Date: Thu, 27 Jun 2013 22:48:07 -0400 Subject: [PATCH 06/10] camera-flags: initial commit Signed-off-by: Benn Snyder --- examples/glview.c | 17 +++- include/libfreenect.h | 23 +++++ src/CMakeLists.txt | 4 +- src/cameras.c | 117 +------------------------- src/flags.c | 191 ++++++++++++++++++++++++++++++++++++++++++ src/flags.h | 38 +++++++++ 6 files changed, 271 insertions(+), 119 deletions(-) create mode 100644 src/flags.c create mode 100644 src/flags.h diff --git a/examples/glview.c b/examples/glview.c index 979546de..caf7dd56 100644 --- a/examples/glview.c +++ b/examples/glview.c @@ -179,6 +179,21 @@ void keyPressed(unsigned char key, int x, int y) freenect_angle = -30; } } + if (key == 'e') { + static freenect_flag_value auto_exposure = FREENECT_ON; + freenect_set_flag(f_dev, FREENECT_AUTO_EXPOSURE, auto_exposure); + auto_exposure = !auto_exposure; + } + if (key == 'b') { + static freenect_flag_value white_balance = FREENECT_ON; + freenect_set_flag(f_dev, FREENECT_AUTO_WHITE_BALANCE, white_balance); + white_balance = !white_balance; + } + if (key == 'r') { + static freenect_flag_value raw_color = FREENECT_ON; + freenect_set_flag(f_dev, FREENECT_RAW_COLOR, raw_color); + raw_color = !raw_color; + } if (key == '1') { freenect_set_led(f_dev,LED_GREEN); } @@ -348,7 +363,7 @@ void *freenect_threadfunc(void *arg) freenect_start_depth(f_dev); freenect_start_video(f_dev); - printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format\n"); + printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format, 'e' - auto exposure, 'b' - white balance, r - raw color\n"); while (!die && freenect_process_events(f_ctx) >= 0) { //Throttle the text output diff --git a/include/libfreenect.h b/include/libfreenect.h index 13c7c4c5..381d286e 100644 --- a/include/libfreenect.h +++ b/include/libfreenect.h @@ -106,6 +106,19 @@ typedef enum { FREENECT_DEPTH_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */ } freenect_depth_format; +/// Enumeration of flags to toggle features with freenect_set_flag() +typedef enum { + FREENECT_AUTO_EXPOSURE = 1 << 14, + FREENECT_AUTO_WHITE_BALANCE = 1 << 1, + FREENECT_RAW_COLOR = 1 << 4, +} freenect_flag; + +/// Possible values for setting each `freenect_flag` +typedef enum { + FREENECT_ON = 1, + FREENECT_OFF = 0, +} freenect_flag_value; + /// Structure to give information about the width, height, bitrate, /// framerate, and buffer size of a frame in a particular mode, as /// well as the total number of bytes needed to hold a single frame. @@ -614,6 +627,16 @@ FREENECTAPI freenect_frame_mode freenect_find_depth_mode(freenect_resolution res */ FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode); +/** + * Enables or disables the specified flag. + * + * @param flag Feature to set + * @param value `FREENECT_ON` or `FREENECT_OFF` + * + * @return 0 on success, < 0 if error + */ +FREENECTAPI int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value); + #ifdef __cplusplus } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e70b6e73..e248ec45 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,10 +8,10 @@ set(CMAKE_C_FLAGS "-Wall") include_directories(${LIBUSB_1_INCLUDE_DIRS}) IF(WIN32) - LIST(APPEND SRC core.c tilt.c cameras.c usb_libusb10.c registration.c ../platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp ../platform/windows/libusb10emu/libusb-1.0/failguard.cpp) + LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c ../platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp ../platform/windows/libusb10emu/libusb-1.0/failguard.cpp) set_source_files_properties(${SRC} PROPERTIES LANGUAGE CXX) ELSE(WIN32) - LIST(APPEND SRC core.c tilt.c cameras.c usb_libusb10.c registration.c) + LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c) ENDIF(WIN32) IF(BUILD_AUDIO) diff --git a/src/cameras.c b/src/cameras.c index 7886a332..0b4fd1a7 100644 --- a/src/cameras.c +++ b/src/cameras.c @@ -32,6 +32,7 @@ #include "freenect_internal.h" #include "registration.h" #include "cameras.h" +#include "flags.h" #define MAKE_RESERVED(res, fmt) (uint32_t)(((res & 0xff) << 8) | (((fmt & 0xff)))) #define RESERVED_TO_RESOLUTION(reserved) (freenect_resolution)((reserved >> 8) & 0xff) @@ -650,122 +651,6 @@ static void video_process(freenect_device *dev, uint8_t *pkt, int len) dev->video_cb(dev, dev->video.proc_buf, dev->video.timestamp); } -typedef struct { - uint8_t magic[2]; - uint16_t len; - uint16_t cmd; - uint16_t tag; -} cam_hdr; - -static int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len) -{ - freenect_context *ctx = dev->parent; - int res, actual_len; - uint8_t obuf[0x400]; - uint8_t ibuf[0x200]; - cam_hdr *chdr = (cam_hdr*)obuf; - cam_hdr *rhdr = (cam_hdr*)ibuf; - - if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) { - FN_ERROR("send_cmd: Invalid command length (0x%x)\n", cmd_len); - return -1; - } - - chdr->magic[0] = 0x47; - chdr->magic[1] = 0x4d; - chdr->cmd = fn_le16(cmd); - chdr->tag = fn_le16(dev->cam_tag); - chdr->len = fn_le16(cmd_len / 2); - - memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len); - - res = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, cmd_len + sizeof(*chdr)); - FN_SPEW("Control cmd=%04x tag=%04x len=%04x: %d\n", cmd, dev->cam_tag, cmd_len, res); - if (res < 0) { - FN_ERROR("send_cmd: Output control transfer failed (%d)\n", res); - return res; - } - - do { - actual_len = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200); - FN_FLOOD("actual_len: %d\n", actual_len); - } while ((actual_len == 0) || (actual_len == 0x200)); - FN_SPEW("Control reply: %d\n", res); - if (actual_len < (int)sizeof(*rhdr)) { - FN_ERROR("send_cmd: Input control transfer failed (%d)\n", res); - return res; - } - actual_len -= sizeof(*rhdr); - - if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) { - FN_ERROR("send_cmd: Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]); - return -1; - } - if (rhdr->cmd != chdr->cmd) { - FN_ERROR("send_cmd: Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd); - return -1; - } - if (rhdr->tag != chdr->tag) { - FN_ERROR("send_cmd: Bad tag %04x != %04x\n", rhdr->tag, chdr->tag); - return -1; - } - if (fn_le16(rhdr->len) != (actual_len/2)) { - FN_ERROR("send_cmd: Bad len %04x != %04x\n", fn_le16(rhdr->len), (int)(actual_len/2)); - return -1; - } - - if (actual_len > reply_len) { - FN_WARNING("send_cmd: Data buffer is %d bytes long, but got %d bytes\n", reply_len, actual_len); - memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len); - } else { - memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len); - } - - dev->cam_tag++; - - return actual_len; -} - -static int write_register(freenect_device *dev, uint16_t reg, uint16_t data) -{ - freenect_context *ctx = dev->parent; - uint16_t reply[2]; - uint16_t cmd[2]; - int res; - - cmd[0] = fn_le16(reg); - cmd[1] = fn_le16(data); - - FN_DEBUG("Write Reg 0x%04x <= 0x%02x\n", reg, data); - res = send_cmd(dev, 0x03, cmd, 4, reply, 4); - if (res < 0) - return res; - if (res != 2) { - FN_WARNING("send_cmd returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); - } - return 0; -} - -// This function is here for completeness. We don't actually use it for anything right now. -static uint16_t read_register(freenect_device *dev, uint16_t reg) -{ - freenect_context *ctx = dev->parent; - uint16_t reply[2]; - uint16_t cmd; - int res; - - cmd = fn_le16(reg); - - FN_DEBUG("Read Reg 0x%04x =>\n", reg); - res = send_cmd(dev, 0x02, &cmd, 2, reply, 4); - if (res < 0) - FN_ERROR("read_register: send_cmd() failed: %d\n", res); - if (res != 4) - FN_WARNING("send_cmd returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); - - return reply[1]; -} - static int freenect_fetch_reg_info(freenect_device *dev) { freenect_context *ctx = dev->parent; diff --git a/src/flags.c b/src/flags.c new file mode 100644 index 00000000..780e2421 --- /dev/null +++ b/src/flags.c @@ -0,0 +1,191 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2010-2011 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 // for memcpy +#include "freenect_internal.h" +#include "flags.h" + + +// freenect_set_flag is the only function exposed in libfreenect.h +// The rest are available internally via #include flags.h + + +int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value) +{ + uint16_t reg = read_cmos_register(dev, 0x0106); + if (reg < 0) + return reg; + if (value == FREENECT_ON) + reg |= flag; + else + reg &= ~flag; + return write_cmos_register(dev, 0x0106, reg); +} + +typedef struct { + uint8_t magic[2]; + uint16_t len; + uint16_t cmd; + uint16_t tag; +} cam_hdr; + +FN_INTERNAL int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len) +{ + freenect_context *ctx = dev->parent; + int res, actual_len; + uint8_t obuf[0x400]; + uint8_t ibuf[0x200]; + cam_hdr *chdr = (cam_hdr*)obuf; + cam_hdr *rhdr = (cam_hdr*)ibuf; + + if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) { + FN_ERROR("send_cmd: Invalid command length (0x%x)\n", cmd_len); + return -1; + } + + chdr->magic[0] = 0x47; + chdr->magic[1] = 0x4d; + chdr->cmd = fn_le16(cmd); + chdr->tag = fn_le16(dev->cam_tag); + chdr->len = fn_le16(cmd_len / 2); + + memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len); + + res = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, cmd_len + sizeof(*chdr)); + FN_SPEW("send_cmd: cmd=%04x tag=%04x len=%04x: %d\n", cmd, dev->cam_tag, cmd_len, res); + if (res < 0) { + FN_ERROR("send_cmd: Output control transfer failed (%d)\n", res); + return res; + } + + do { + actual_len = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200); + FN_FLOOD("send_cmd: actual length = %d\n", actual_len); + } while ((actual_len == 0) || (actual_len == 0x200)); + FN_SPEW("Control reply: %d\n", res); + if (actual_len < (int)sizeof(*rhdr)) { + FN_ERROR("send_cmd: Input control transfer failed (%d)\n", res); + return res; + } + actual_len -= sizeof(*rhdr); + + if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) { + FN_ERROR("send_cmd: Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]); + return -1; + } + if (rhdr->cmd != chdr->cmd) { + FN_ERROR("send_cmd: Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd); + return -1; + } + if (rhdr->tag != chdr->tag) { + FN_ERROR("send_cmd: Bad tag %04x != %04x\n", rhdr->tag, chdr->tag); + return -1; + } + if (fn_le16(rhdr->len) != (actual_len/2)) { + FN_ERROR("send_cmd: Bad len %04x != %04x\n", fn_le16(rhdr->len), (int)(actual_len/2)); + return -1; + } + + if (actual_len > reply_len) { + FN_WARNING("send_cmd: Data buffer is %d bytes long, but got %d bytes\n", reply_len, actual_len); + memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len); + } else { + memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len); + } + + dev->cam_tag++; + + return actual_len; +} + +FN_INTERNAL uint16_t read_register(freenect_device *dev, uint16_t reg) +{ + freenect_context *ctx = dev->parent; + uint16_t reply[2]; + uint16_t cmd; + int res; + + cmd = fn_le16(reg); + + FN_DEBUG("read_register: 0x%04x =>\n", reg); + res = send_cmd(dev, 0x02, &cmd, 2, reply, 4); + if (res < 0) + FN_ERROR("read_register: send_cmd() failed: %d\n", res); + if (res != 4) + FN_WARNING("read_register: send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); + + return reply[1]; +} + +FN_INTERNAL int write_register(freenect_device *dev, uint16_t reg, uint16_t data) +{ + freenect_context *ctx = dev->parent; + uint16_t reply[2]; + uint16_t cmd[2]; + int res; + + cmd[0] = fn_le16(reg); + cmd[1] = fn_le16(data); + + FN_DEBUG("write_register: 0x%04x <= 0x%02x\n", reg, data); + res = send_cmd(dev, 0x03, cmd, 4, reply, 4); + if (res < 0) + return res; + if (res != 2) { + FN_WARNING("send_cmd() returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]); + } + return 0; +} + +FN_INTERNAL uint16_t read_cmos_register(freenect_device *dev, uint16_t reg) +{ + freenect_context *ctx = dev->parent; + uint16_t replybuf[0x200]; + uint16_t cmdbuf[3]; + cmdbuf[0] = 1; + cmdbuf[1] = reg & 0x7fff; + cmdbuf[2] = 0; + int res = send_cmd(dev, 0x95, cmdbuf, 6, replybuf, 6); + if (res < 0) { + FN_ERROR("read_cmos_register: send_cmd() returned %d\n", res); + return res; + } + return replybuf[2]; +} + +FN_INTERNAL int write_cmos_register(freenect_device *dev, uint16_t reg, uint16_t value) +{ + freenect_context *ctx = dev->parent; + uint16_t replybuf[0x200]; + uint16_t cmdbuf[3]; + cmdbuf[0] = 1; + cmdbuf[1] = reg | 0x8000; + cmdbuf[2] = value; + int res = send_cmd(dev, 0x95, cmdbuf, 6, replybuf, 6); + if (res < 0) + FN_ERROR("read_cmos_register: send_cmd() returned %d\n", res); + return res; +} diff --git a/src/flags.h b/src/flags.h new file mode 100644 index 00000000..87e401df --- /dev/null +++ b/src/flags.h @@ -0,0 +1,38 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2010-2011 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. + */ + +#pragma once + +#include "libfreenect.h" + + +int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len); + +uint16_t read_register(freenect_device *dev, uint16_t reg); +int write_register(freenect_device *dev, uint16_t reg, uint16_t data); + +uint16_t read_cmos_register(freenect_device *dev, uint16_t reg); +int write_cmos_register(freenect_device *dev, uint16_t reg, uint16_t value); From 37758b2fb516a66d630a703885d937d1994d844b Mon Sep 17 00:00:00 2001 From: Benn Snyder Date: Sun, 30 Jun 2013 13:01:51 -0400 Subject: [PATCH 07/10] camera-flags: added depth and video mirror Signed-off-by: Benn Snyder --- examples/glview.c | 9 ++++++++- include/libfreenect.h | 12 ++++++++---- src/flags.c | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/examples/glview.c b/examples/glview.c index caf7dd56..f2edcf1b 100644 --- a/examples/glview.c +++ b/examples/glview.c @@ -194,6 +194,12 @@ void keyPressed(unsigned char key, int x, int y) freenect_set_flag(f_dev, FREENECT_RAW_COLOR, raw_color); raw_color = !raw_color; } + if (key == 'm') { + static freenect_flag_value mirror = FREENECT_ON; + freenect_set_flag(f_dev, FREENECT_MIRROR_DEPTH, mirror); + freenect_set_flag(f_dev, FREENECT_MIRROR_VIDEO, mirror); + mirror = !mirror; + } if (key == '1') { freenect_set_led(f_dev,LED_GREEN); } @@ -363,7 +369,8 @@ void *freenect_threadfunc(void *arg) freenect_start_depth(f_dev); freenect_start_video(f_dev); - printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format, 'e' - auto exposure, 'b' - white balance, r - raw color\n"); + printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format\n"); + printf("'e' - auto exposure, 'b' - white balance, 'r' - raw color, 'm' - mirror\n"); while (!die && freenect_process_events(f_ctx) >= 0) { //Throttle the text output diff --git a/include/libfreenect.h b/include/libfreenect.h index 381d286e..55ac3279 100644 --- a/include/libfreenect.h +++ b/include/libfreenect.h @@ -108,15 +108,19 @@ typedef enum { /// Enumeration of flags to toggle features with freenect_set_flag() typedef enum { - FREENECT_AUTO_EXPOSURE = 1 << 14, + // values written to the CMOS register + FREENECT_AUTO_EXPOSURE = 1 << 14, FREENECT_AUTO_WHITE_BALANCE = 1 << 1, - FREENECT_RAW_COLOR = 1 << 4, + FREENECT_RAW_COLOR = 1 << 4, + // registers to be written with 0 or 1 + FREENECT_MIRROR_DEPTH = 0x0017, + FREENECT_MIRROR_VIDEO = 0x0047, } freenect_flag; /// Possible values for setting each `freenect_flag` typedef enum { - FREENECT_ON = 1, FREENECT_OFF = 0, + FREENECT_ON = 1, } freenect_flag_value; /// Structure to give information about the width, height, bitrate, @@ -631,7 +635,7 @@ FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_fra * Enables or disables the specified flag. * * @param flag Feature to set - * @param value `FREENECT_ON` or `FREENECT_OFF` + * @param value `FREENECT_OFF` or `FREENECT_ON` * * @return 0 on success, < 0 if error */ diff --git a/src/flags.c b/src/flags.c index 780e2421..85c6d0e0 100644 --- a/src/flags.c +++ b/src/flags.c @@ -35,6 +35,9 @@ int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value) { + if (flag == FREENECT_MIRROR_DEPTH || flag == FREENECT_MIRROR_VIDEO) + return write_register(dev, flag, value); + uint16_t reg = read_cmos_register(dev, 0x0106); if (reg < 0) return reg; From baa489a863712d930831b41040bf607f2857857d Mon Sep 17 00:00:00 2001 From: Benn Snyder Date: Wed, 10 Jul 2013 21:57:54 -0400 Subject: [PATCH 08/10] as3-bom: Support uncompressed depth Signed-off-by: Benn Snyder --- wrappers/actionscript/server/as3-server.c | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/wrappers/actionscript/server/as3-server.c b/wrappers/actionscript/server/as3-server.c index 8b79103d..ac5b476e 100755 --- a/wrappers/actionscript/server/as3-server.c +++ b/wrappers/actionscript/server/as3-server.c @@ -123,17 +123,29 @@ void sendDepth(){ depth = tmp_depth; } - for (i=0; i< depth_mode.width * depth_mode.height; i++) { - buf_depth[4 * i + 0] = 0x00; - buf_depth[4 * i + 1] = 0x00; - buf_depth[4 * i + 2] = 0x00; - buf_depth[4 * i + 3] = 0xFF; + for (i=0; i< depth_mode.width * depth_mode.height; i++) { + if(_depth_compression != 0) { + buf_depth[3 * i + 0] = 0x00; + buf_depth[3 * i + 1] = 0x00; + buf_depth[3 * i + 2] = 0x00; + } else { + buf_depth[4 * i + 0] = 0x00; + buf_depth[4 * i + 1] = 0x00; + buf_depth[4 * i + 2] = 0x00; + buf_depth[4 * i + 3] = 0xFF; + } if(depth[i] < _max_depth && depth[i] > _min_depth){ unsigned char l = 0xFF - ((depth[i] - _min_depth) & 0xFF); - buf_depth[4 * i + 0] = l; - buf_depth[4 * i + 1] = l; - buf_depth[4 * i + 2] = l; - buf_depth[4 * i + 3] = 0xFF; + if(_depth_compression != 0) { + buf_depth[3 * i + 0] = l; + buf_depth[3 * i + 1] = l; + buf_depth[3 * i + 2] = l; + } else { + buf_depth[4 * i + 0] = l; + buf_depth[4 * i + 1] = l; + buf_depth[4 * i + 2] = l; + buf_depth[4 * i + 3] = 0xFF; + } } } if(_depth_compression != 0) { From 955af59d324ea73890118ee2ee56814a7303b830 Mon Sep 17 00:00:00 2001 From: Benn Snyder Date: Tue, 16 Jul 2013 18:46:55 -0400 Subject: [PATCH 09/10] Changed all GL-related INCLUDE_DIRS to INCLUDE_DIR Fixes #320 Signed-off-by: Benn Snyder --- examples/CMakeLists.txt | 2 +- wrappers/cpp/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 506ca9bd..3ae566e8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -56,7 +56,7 @@ else() find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) - include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) target_link_libraries(glview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) target_link_libraries(regview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) diff --git a/wrappers/cpp/CMakeLists.txt b/wrappers/cpp/CMakeLists.txt index bb9c53cb..ff8469f7 100644 --- a/wrappers/cpp/CMakeLists.txt +++ b/wrappers/cpp/CMakeLists.txt @@ -25,7 +25,7 @@ else() find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) - include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} ${USB_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${USB_INCLUDE_DIRS}) target_link_libraries(cppview freenect ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIB}) endif() From 3ef82585695605d40be9bd0a1dc4a882fbb3a4af Mon Sep 17 00:00:00 2001 From: Yannis Gravezas Date: Tue, 23 Apr 2013 14:35:33 +0300 Subject: [PATCH 10/10] Kinect for Windows and Xbox 360 Model 1473 support This patch does auto detection of all three models and disables motor subdevice for the 2 newer ones. It also adds a function to test for the presence of the motor and audio devices on newer models. Signed-off-by: Yannis Gravezas (wizgrav) --- include/libfreenect.h | 9 ++++ .../windows/libusb10emu/libusb-1.0/libusb.h | 1 + .../libusb10emu/libusb-1.0/libusbemu.cpp | 11 +++++ src/cameras.c | 6 +-- src/core.c | 4 ++ src/freenect_internal.h | 3 ++ src/tilt.c | 8 ++++ src/usb_libusb10.c | 42 ++++++++++++++++--- 8 files changed, 75 insertions(+), 9 deletions(-) diff --git a/include/libfreenect.h b/include/libfreenect.h index 13c7c4c5..1648a756 100644 --- a/include/libfreenect.h +++ b/include/libfreenect.h @@ -302,6 +302,15 @@ FREENECTAPI int freenect_supported_subdevices(void); */ FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs); +/** + * Returns the devices that are enabled after calls to freenect_open_device() + * On newer kinects the motor and audio are automatically disabled for now + * + * @param ctx Context to set future subdevice selection for + * @return Flags representing the subdevices that were actually opened (see freenect_device_flags) + */ +FREENECTAPI freenect_device_flags freenect_enabled_subdevices(freenect_context *ctx); + /** * Opens a kinect device via a context. Index specifies the index of * the device on the current state of the bus. Bus resets may cause diff --git a/platform/windows/libusb10emu/libusb-1.0/libusb.h b/platform/windows/libusb10emu/libusb-1.0/libusb.h index 33b32887..38c3c1a9 100644 --- a/platform/windows/libusb10emu/libusb-1.0/libusb.h +++ b/platform/windows/libusb10emu/libusb-1.0/libusb.h @@ -77,6 +77,7 @@ int libusb_get_string_descriptor(libusb_device_handle *dev_handle, uint8_t desc_ int libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length); int libusb_set_configuration(libusb_device_handle *dev, int configuration); +int libusb_set_interface_alt_setting(libusb_device_handle *dev,int interface_number,int alternate_setting); int libusb_claim_interface(libusb_device_handle* dev, int interface_number); int libusb_release_interface(libusb_device_handle* dev, int interface_number); diff --git a/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp b/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp index af39ff68..79361e1f 100644 --- a/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp +++ b/platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp @@ -302,6 +302,17 @@ int libusb_set_configuration(libusb_device_handle *dev, int configuration) return 0; } +int libusb_set_interface_alt_setting(libusb_device_handle *dev, int interface_number,int alternate_setting){ + RAIIMutex lock (dev->dev->ctx->mutex); + if (0 != usb_set_altinterface(dev->handle, alternate_setting)) + { + LIBUSBEMU_ERROR_LIBUSBWIN32(); + return(LIBUSB_ERROR_OTHER); + } + + return(0); +} + int libusb_claim_interface(libusb_device_handle* dev, int interface_number) { RAIIMutex lock (dev->dev->ctx->mutex); diff --git a/src/cameras.c b/src/cameras.c index 7886a332..0483c2ed 100644 --- a/src/cameras.c +++ b/src/cameras.c @@ -904,9 +904,9 @@ static int freenect_fetch_zero_plane_info(freenect_device *dev) uint16_t cmd[5] = {0}; // Offset is the only field in this command, and it's 0 int res; - res = send_cmd(dev, 0x04, cmd, 10, reply, 322); //OPCODE_GET_FIXED_PARAMS = 4, - if (res != 322) { - FN_ERROR("freenect_fetch_zero_plane_info: send_cmd read %d bytes (expected 322)\n", res); + res = send_cmd(dev, 0x04, cmd, 10, reply, ctx->zero_plane_res); //OPCODE_GET_FIXED_PARAMS = 4, + if (res != ctx->zero_plane_res) { + FN_ERROR("freenect_fetch_zero_plane_info: send_cmd read %d bytes (expected %d)\n", res,ctx->zero_plane_res); return -1; } diff --git a/src/core.c b/src/core.c index ecc5942f..305c9e18 100644 --- a/src/core.c +++ b/src/core.c @@ -148,6 +148,10 @@ FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_devi )); } +FREENECTAPI freenect_device_flags freenect_enabled_subdevices(freenect_context *ctx) { + return ctx->enabled_subdevices; +} + FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index) { int res; diff --git a/src/freenect_internal.h b/src/freenect_internal.h index 640d23b6..8df4ee22 100644 --- a/src/freenect_internal.h +++ b/src/freenect_internal.h @@ -52,6 +52,7 @@ struct _freenect_context { fnusb_ctx usb; freenect_device_flags enabled_subdevices; freenect_device *first; + int zero_plane_res; }; #define LL_FATAL FREENECT_LOG_FATAL @@ -131,6 +132,8 @@ static inline int32_t fn_le32s(int32_t s) #define PID_NUI_AUDIO 0x02ad #define PID_NUI_CAMERA 0x02ae #define PID_NUI_MOTOR 0x02b0 +#define PID_K4W_CAMERA 0x02bf +#define PID_K4W_AUDIO 0x02be typedef struct { int running; diff --git a/src/tilt.c b/src/tilt.c index 1a466499..8852e768 100644 --- a/src/tilt.c +++ b/src/tilt.c @@ -47,6 +47,8 @@ freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev) int freenect_update_tilt_state(freenect_device *dev) { freenect_context *ctx = dev->parent; + if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) + return 0; uint8_t buf[10]; uint16_t ux, uy, uz; int ret = fnusb_control(&dev->usb_motor, 0xC0, 0x32, 0x0, 0x0, buf, 10); @@ -70,6 +72,9 @@ int freenect_update_tilt_state(freenect_device *dev) int freenect_set_tilt_degs(freenect_device *dev, double angle) { + freenect_context *ctx = dev->parent; + if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) + return 0; int ret; uint8_t empty[0x1]; @@ -82,6 +87,9 @@ int freenect_set_tilt_degs(freenect_device *dev, double angle) int freenect_set_led(freenect_device *dev, freenect_led_options option) { + freenect_context *ctx = dev->parent; + if(!(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) + return 0; int ret; uint8_t empty[0x1]; ret = fnusb_control(&dev->usb_motor, 0x40, 0x06, (uint16_t)option, 0x0, empty, 0x0); diff --git a/src/usb_libusb10.c b/src/usb_libusb10.c index 065bf6f6..451d2012 100644 --- a/src/usb_libusb10.c +++ b/src/usb_libusb10.c @@ -47,7 +47,7 @@ FN_INTERNAL int fnusb_num_devices(fnusb_ctx *ctx) int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; - if (desc.idVendor == VID_MICROSOFT && desc.idProduct == PID_NUI_CAMERA) + if (desc.idVendor == VID_MICROSOFT && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) nr++; } libusb_free_device_list (devs, 1); @@ -76,7 +76,7 @@ FN_INTERNAL int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_dev int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; - if (desc.idVendor == VID_MICROSOFT && desc.idProduct == PID_NUI_CAMERA) { + if (desc.idVendor == VID_MICROSOFT && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // Verify that a serial number exists to query. If not, don't touch the device. if (desc.iSerialNumber == 0) { continue; @@ -188,9 +188,9 @@ FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) if (desc.idVendor != VID_MICROSOFT) continue; - + res = 0; // Search for the camera - if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && desc.idProduct == PID_NUI_CAMERA) { + if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // If the index given by the user matches our camera index if (nr_cam == index) { res = libusb_open (devs[i], &dev->usb_cam.dev); @@ -199,6 +199,15 @@ FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) dev->usb_cam.dev = NULL; break; } + if(desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)){ + /* Not the old kinect so we only set up the camera*/ + ctx->enabled_subdevices = FREENECT_DEVICE_CAMERA; + ctx->zero_plane_res = 334; + }else{ + /* The good old kinect that tilts and tweets */ + ctx->zero_plane_res = 322; + } + #ifndef _WIN32 // Detach an existing kernel driver for the device res = libusb_kernel_driver_active(dev->usb_cam.dev, 0); @@ -219,12 +228,33 @@ FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) dev->usb_cam.dev = NULL; break; } + if(desc.idProduct == PID_K4W_CAMERA){ + res = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1); + if (res != 0) { + FN_ERROR("Failed to set alternate interface #1 for K4W: %d\n", res); + libusb_close(dev->usb_cam.dev); + dev->usb_cam.dev = NULL; + break; + } + + } } else { nr_cam++; } } - + } + + if(ctx->enabled_subdevices == FREENECT_DEVICE_CAMERA || res < 0) cnt = 0; + // Search for the motor + + for (i = 0; i < cnt; i++) { + int r = libusb_get_device_descriptor (devs[i], &desc); + if (r < 0) + continue; + + if (desc.idVendor != VID_MICROSOFT) + continue; if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) { // If the index given by the user matches our camera index if (nr_mot == index) { @@ -249,7 +279,7 @@ FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) #ifdef BUILD_AUDIO // TODO: check that the firmware has already been loaded; if not, upload firmware. // Search for the audio - if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && desc.idProduct == PID_NUI_AUDIO) { + if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || desc.idProduct == PID_K4W_AUDIO)) { // If the index given by the user matches our audio index if (nr_audio == index) { res = libusb_open (devs[i], &dev->usb_audio.dev);