Permalink
Browse files

Supports loading audio fw from memory as well as disk. Supports tilt,…

…accel and led for K4W and 1473 device. Adds keep alive for K4W and 1473. Signed-off-by: Theodore Watson theo@openframeworks.cc (ofTheo)
  • Loading branch information...
1 parent dfc6661 commit 9ac4ab13fd62df25fc2977fef8e839a2a04b03c1 @ofTheo ofTheo committed Jan 28, 2014
Showing with 438 additions and 41 deletions.
  1. +20 −0 include/libfreenect.h
  2. +3 −0 src/audio.c
  3. +14 −0 src/core.c
  4. +16 −0 src/freenect_internal.h
  5. +19 −2 src/keep_alive.c
  6. +87 −25 src/loader.c
  7. +4 −1 src/loader.h
  8. +217 −1 src/tilt.c
  9. +58 −12 src/usb_libusb10.c
View
@@ -669,6 +669,26 @@ FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_fra
*/
FREENECTAPI int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value);
+
+/**
+ * Allows the user to specify a pointer to the audio firmware in memory for the Xbox 360 Kinect
+ *
+ * @param ctx Context to open device through
+ * @param fw_ptr Pointer to audio firmware loaded in memory
+ * @param num_bytes The size of the firmware in bytes
+ */
+FREENECTAPI void freenect_set_fw_address_nui(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes);
+
+/**
+ * Allows the user to specify a pointer to the audio firmware in memory for the K4W Kinect
+ *
+ * @param ctx Context to open device through
+ * @param fw_ptr Pointer to audio firmware loaded in memory
+ * @param num_bytes The size of the firmware in bytes
+ */
+FREENECTAPI void freenect_set_fw_address_k4w(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes);
+
+
#ifdef __cplusplus
}
#endif
View
@@ -30,6 +30,8 @@
#include <string.h>
#include <stdlib.h>
+#ifdef BUILD_AUDIO
+
static void prepare_iso_out_data(freenect_device* dev, uint8_t* buffer) {
audio_stream* stream = &dev->audio;
if (dev->audio_out_cb) {
@@ -238,3 +240,4 @@ int freenect_stop_audio(freenect_device* dev) {
return ret;
}
+#endif
View
@@ -293,3 +293,17 @@ FN_INTERNAL void fn_log(freenect_context *ctx, freenect_loglevel level, const ch
va_end(ap);
}
}
+
+
+FREENECTAPI void freenect_set_fw_address_nui(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes)
+{
+ ctx->fn_fw_nui_ptr = fw_ptr;
+ ctx->fn_fw_nui_size = num_bytes;
+}
+
+FREENECTAPI void freenect_set_fw_address_k4w(freenect_context * ctx, unsigned char * fw_ptr, unsigned int num_bytes)
+{
+ ctx->fn_fw_k4w_ptr = fw_ptr;
+ ctx->fn_fw_k4w_size = num_bytes;
+}
+
View
@@ -53,6 +53,13 @@ struct _freenect_context {
freenect_device_flags enabled_subdevices;
freenect_device *first;
int zero_plane_res;
+
+ //if you want to load firmware from memory rather than disk
+ unsigned char * fn_fw_nui_ptr;
+ unsigned int fn_fw_nui_size;
+
+ unsigned char * fn_fw_k4w_ptr;
+ unsigned int fn_fw_k4w_size;
};
#define LL_FATAL FREENECT_LOG_FATAL
@@ -133,7 +140,13 @@ static inline int32_t fn_le32s(int32_t s)
#define PID_NUI_CAMERA 0x02ae
#define PID_NUI_MOTOR 0x02b0
#define PID_K4W_CAMERA 0x02bf
+
+// For K4W: first pid is what it starts out as,
+// second is how it appears with lastest firmware from SDK,
+// third is from beta SDK firmware ( which is what is unpacked by the fw script and doesn't support motor control )
#define PID_K4W_AUDIO 0x02be
+#define PID_K4W_AUDIO_ALT_1 0x02c3
+#define PID_K4W_AUDIO_ALT_2 0x02bb
typedef struct {
int running;
@@ -243,4 +256,7 @@ struct _freenect_device {
// Motor
fnusb_dev usb_motor;
freenect_raw_tilt_state raw_state;
+
+ int device_does_motor_control_with_audio;
+ int motor_control_with_audio_enabled;
};
View
@@ -63,6 +63,7 @@
#include "keep_alive.h"
+#include "freenect_internal.h"
#include <libusb-1.0/libusb.h>
#include <stdio.h>
@@ -157,14 +158,30 @@ static int set_led(libusb_device_handle* dev, int state) {
void freenect_extra_keep_alive(int pid){
int res;
- int state_to_set = 4;
+ int state_to_set = 3;
libusb_context* ctx = NULL;
libusb_init(&ctx);
libusb_device_handle* dev = NULL;
+
+ //check the default audio device
+ dev = libusb_open_device_with_vid_pid(ctx, 0x045e, pid);
+
+ //K4W only:
+ //if the firmware is uploaded the device could have a two different PIDs based on which firmware was uploaded.
+ //so we have to check for both
+ //note: it might be better if we pass in the PID of the camera and then find the audio device that is in the same usb tree/hub - might be more reliable when multiple devices are plugged in
+ if( dev == NULL && pid == PID_K4W_AUDIO ){
+ pid = PID_K4W_AUDIO_ALT_1;
+ dev = libusb_open_device_with_vid_pid(ctx, 0x045e, pid);
+ }
+ if( dev == NULL && pid == PID_K4W_AUDIO_ALT_1 ){
+ pid = PID_K4W_AUDIO_ALT_2;
dev = libusb_open_device_with_vid_pid(ctx, 0x045e, pid);
- if (dev == NULL) {
+ }
+
+ if(dev == NULL) {
LOG("freenect extra keepAlive: Failed to open audio device\n");
libusb_exit(ctx);
return;
View
@@ -32,6 +32,8 @@
#include <stdio.h>
#include <stdlib.h>
+#ifdef BUILD_AUDIO
+
static void dump_bl_cmd(freenect_context* ctx, bootloader_command cmd) {
int i;
for(i = 0; i < 24; i++)
@@ -120,28 +122,28 @@ static int check_version_string(fnusb_dev* dev) {
return res;
}
-FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
- freenect_context* ctx = dev->parent->parent;
- bootloader_command bootcmd;
- memset(&bootcmd, 0, sizeof(bootcmd));
- bootcmd.magic = fn_le32(0x06022009);
-
- int res;
- int transferred;
+FN_INTERNAL int upload_firmware(fnusb_dev* dev, char * filename) {
+ freenect_context* ctx = dev->parent->parent;
/* Search for firmware file (audios.bin) in the following places:
* $LIBFREENECT_FIRMWARE_PATH
* .
* ${HOME}/.libfreenect
* /usr/local/share/libfreenect
* /usr/share/libfreenect
+ * ./../Resources/ ( for OS X )
*/
- const char* fw_filename = "/audios.bin";
+
+ //need to add a forward slash
+ char fw_filename[1024];
+ sprintf(fw_filename, "/%s", filename);
+
int filenamelen = strlen(fw_filename);
int i;
int searchpathcount;
FILE* fw = NULL;
- for(i = 0, searchpathcount = 5; !fw && i < searchpathcount; i++) {
+
+ for(i = 0, searchpathcount = 6; !fw && i < searchpathcount; i++) {
char* fwfile;
int needs_free = 0;
switch(i) {
@@ -157,7 +159,10 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
}
break;
case 1:
- fwfile = "./audios.bin";
+ //fwfile = "./audios.bin";
+ fwfile = malloc(2048);
+ needs_free = 1;
+ sprintf(fwfile, ".%s", fw_filename);
break;
case 2: {
// Construct $HOME/.libfreenect/
@@ -175,10 +180,21 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
}
break;
case 3:
- fwfile = "/usr/local/share/libfreenect/audios.bin";
+ //fwfile = "/usr/local/share/libfreenect/audios.bin";
+ sprintf(fwfile, "/usr/local/share/libfreenect%s", fw_filename);
+
break;
case 4:
- fwfile = "/usr/share/libfreenect/audios.bin";
+ //fwfile = "/usr/share/libfreenect/audios.bin";
+ fwfile = malloc(2048);
+ needs_free = 1;
+ sprintf(fwfile, "/usr/share/libfreenect%s", fw_filename);
+ break;
+ case 5:
+ //fwfile = "./../Resources/audios.bin"; //default for OS X equivilant to: "./audios.bin";
+ fwfile = malloc(2048);
+ needs_free = 1;
+ sprintf(fwfile, "./../Resources%s", fw_filename);
break;
default: break;
}
@@ -192,15 +208,50 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
FN_ERROR("upload_firmware: failed to find firmware file.\n");
return -errno;
}
- // Now we have an open firmware file handle.
+
+ // get the number of bytes of the file
+ fseek(fw , 0, SEEK_END);
+ int fw_num_bytes = ftell(fw);
+ rewind(fw);
+
+ if( fw_num_bytes <= 0 ){
+ FN_ERROR("upload_firmware: failed to find file with any data.\n");
+ return -errno;
+ }
+
+ unsigned char * fw_bytes = malloc(fw_num_bytes);
+ int numRead = fread(fw_bytes, 1, fw_num_bytes, fw);
+ fw_num_bytes = numRead; // just in case
+
+ int retVal = upload_firmware_from_memory(dev, fw_bytes, fw_num_bytes);
+
+ fclose(fw);
+ fw = NULL;
+
+ return retVal;
+ }
+
+FN_INTERNAL int upload_firmware_from_memory(fnusb_dev* dev, unsigned char * fw_from_mem, unsigned int fw_size_in_btyes) {
+ freenect_context* ctx = dev->parent->parent;
+ bootloader_command bootcmd;
+ memset(&bootcmd, 0, sizeof(bootcmd));
+ bootcmd.magic = fn_le32(0x06022009);
+
+ int res;
+ int transferred;
+
firmware_header fwheader;
int read = 0;
- read = fread(&fwheader, 1, sizeof(firmware_header), fw);
- if (read != sizeof(firmware_header)) {
+ int bytesLeft = fw_size_in_btyes;
+ unsigned char * readPtr = &fw_from_mem[0];
+
+ if (fw_size_in_btyes < sizeof(firmware_header)) {
FN_ERROR("upload_firmware: firmware image too small, has no header?\n");
- fclose(fw);
return -errno;
}
+
+ memcpy(&fwheader, readPtr, sizeof(firmware_header));
+
// The file is serialized as little endian.
fwheader.magic = fn_le32(fwheader.magic);
fwheader.ver_major = fn_le16(fwheader.ver_major);
@@ -217,16 +268,27 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
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 readIndex = 0;
int total_bytes_sent = 0;
do {
- 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) {
+
+ read = (0x4000 > fwheader.size - total_bytes_sent) ? fwheader.size - total_bytes_sent : 0x4000;
+
+ // sanity check
+ if( read > bytesLeft ){
+ read = bytesLeft;
+ }
+ if (read <= 0) {
break;
}
+
+ memcpy(page, &readPtr[readIndex], read);
+ readIndex += read;
+ bytesLeft -= read;
+
bootcmd.tag = fn_le32(dev->parent->audio_tag);
bootcmd.bytes = fn_le32(read);
bootcmd.cmd = fn_le32(0x03);
@@ -237,7 +299,6 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred);
if(res != 0 || transferred != sizeof(bootcmd)) {
FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)(sizeof(bootcmd)));
- fclose(fw);
return -1;
}
int bytes_sent = 0;
@@ -246,7 +307,6 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
res = fnusb_bulk(dev, 1, &page[bytes_sent], to_send, &transferred);
if(res != 0 || transferred != to_send) {
FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, to_send);
- fclose(fw);
return -1;
}
bytes_sent += to_send;
@@ -256,8 +316,7 @@ FN_INTERNAL int upload_firmware(fnusb_dev* dev) {
addr += (uint32_t)read;
dev->parent->audio_tag++;
} 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;
@@ -359,3 +418,6 @@ FN_INTERNAL int upload_cemd_data(fnusb_dev* dev) {
FN_INFO("CEMD data uploaded successfully.\n");
return 0;
}
+
+#endif
+
View
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "usb_libusb10.h"
+
typedef struct {
uint32_t magic;
uint32_t tag;
@@ -64,5 +65,7 @@ typedef struct {
uint32_t status;
} bootloader_status_code;
-int upload_firmware(fnusb_dev* dev);
+int upload_firmware(fnusb_dev* dev, char * fw_filename);
+int upload_firmware_from_memory(fnusb_dev* dev, unsigned char * fw_from_mem, unsigned int fw_size_in_bytes);
+
int upload_cemd_data(fnusb_dev* dev);
Oops, something went wrong.

0 comments on commit 9ac4ab1

Please sign in to comment.