Skip to content

Commit

Permalink
Supports loading audio fw from memory as well as disk. Supports tilt,…
Browse files Browse the repository at this point in the history
…accel and led for K4W and 1473 device. Adds keep alive for K4W and 1473. Signed-off-by: Theodore Watson [email protected] (ofTheo)
  • Loading branch information
ofTheo committed Jan 28, 2014
1 parent dfc6661 commit 9ac4ab1
Show file tree
Hide file tree
Showing 9 changed files with 438 additions and 41 deletions.
20 changes: 20 additions & 0 deletions include/libfreenect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions src/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -238,3 +240,4 @@ int freenect_stop_audio(freenect_device* dev) {
return ret;
}

#endif
14 changes: 14 additions & 0 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

16 changes: 16 additions & 0 deletions src/freenect_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
};
21 changes: 19 additions & 2 deletions src/keep_alive.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@


#include "keep_alive.h"
#include "freenect_internal.h"

#include <libusb-1.0/libusb.h>
#include <stdio.h>
Expand Down Expand Up @@ -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;
Expand Down
112 changes: 87 additions & 25 deletions src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand Down Expand Up @@ -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) {
Expand All @@ -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/
Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -359,3 +418,6 @@ FN_INTERNAL int upload_cemd_data(fnusb_dev* dev) {
FN_INFO("CEMD data uploaded successfully.\n");
return 0;
}

#endif

5 changes: 4 additions & 1 deletion src/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <stdint.h>
#include "usb_libusb10.h"


typedef struct {
uint32_t magic;
uint32_t tag;
Expand Down Expand Up @@ -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);
Loading

0 comments on commit 9ac4ab1

Please sign in to comment.