Exemple #1
0
int get_reply(libusb_device_handle* dev, freenect_context *ctx){
	unsigned char buffer[512];
	memset(buffer, 0, 512);
	int transferred = 0;
	int res = 0;
	res = libusb_bulk_transfer(dev, 0x81, buffer, 512, &transferred, 100);
	if (res != 0) {
		FN_ERROR("get_reply(): libusb_bulk_transfer failed: %d (transferred = %d)\n", res, transferred);
	} else if (transferred != 12) {
		FN_ERROR("get_reply(): weird - got %d bytes (expected 12)\n", transferred);
	} else {
		fn_alt_motor_reply reply;
		memcpy(&reply, buffer, sizeof(reply));
		if (reply.magic != 0x0a6fe000) {
			FN_ERROR("Bad magic: %08X (expected 0A6FE000\n", reply.magic);
			res = -1;
		}

        //can't really do this as tag_seq is static. with two cameras this is not going to match. could put in as part of libusb_device but I don't think it really matters.
//		if (reply.tag != tag_next_ack) {
//			FN_ERROR("Reply tag out of order: expected %d, got %d\n", tag_next_ack, reply.tag);
//			res = -1;
//		}

		if (reply.status != 0) {
			FN_ERROR("reply status != 0: failure?\n");
			res = -1;
		}
		
        tag_next_ack++;
	}
	return res;
}
Exemple #2
0
FREENECTAPI int freenect_process_events_timeout(freenect_context *ctx, struct timeval *timeout)
{

    int res = fnusb_process_events_timeout(&ctx->usb, timeout);
    // Iterate over the devices in ctx.  If any of them are flagged as
    freenect_device* dev = ctx->first;
    while(dev) {
        if (dev->usb_cam.device_dead) {
            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,"USB camera marked dead, stopping streams" );
            FN_ERROR("USB camera marked dead, stopping streams\n");
            res = -1;
            freenect_stop_video(dev);
            freenect_stop_depth(dev);
        }
#ifdef BUILD_AUDIO
        if (dev->usb_audio.device_dead) {
            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,"USB audio marked dead, stopping streams" );
            FN_ERROR("USB audio marked dead, stopping streams\n");
            res = -1; // Or something else to tell the user that the device just vanished.
            freenect_stop_audio(dev);
        }
#endif
        dev = dev->next;
    }

    return res;
}
Exemple #3
0
static int get_reply(fnusb_dev* dev) {
	freenect_context* ctx = dev->parent->parent;
	unsigned char dump[512];
	bootloader_status_code buffer;
	int res;
	int transferred;
	res = fnusb_bulk(dev, 0x81, dump, 512, &transferred);
	if(res != 0 || transferred != sizeof(bootloader_status_code)) {
		FN_ERROR("Error reading reply: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)(sizeof(bootloader_status_code)));
		return res;
	}
	memcpy(&buffer, dump, sizeof(bootloader_status_code));
	if(fn_le32(buffer.magic) != 0x0a6fe000) {
		FN_ERROR("Error reading reply: invalid magic %08X\n",buffer.magic);
		return -1;
	}
	if(fn_le32(buffer.tag) != dev->parent->audio_tag) {
		FN_ERROR("Error reading reply: non-matching tag number %08X (expected %08X)\n", buffer.tag, dev->parent->audio_tag);
		return -1;
	}
	if(fn_le32(buffer.status) != 0) {
		FN_ERROR("Notice reading reply: last uint32_t was nonzero: %d\n", buffer.status);
	}
	FN_INFO("Reading reply: ");
	int i;
	for(i = 0; i < transferred; ++i) {
		FN_INFO("%02X ", ((unsigned char*)(&buffer))[i]);
	}
	FN_INFO("\n");
	return res;
}
Exemple #4
0
int freenect_update_tilt_state(freenect_device *dev)
{
	freenect_context *ctx = dev->parent;
	
    #ifdef BUILD_AUDIO
    //if we have motor control via audio and fw is uploaded - call the alt function
    if( dev->motor_control_with_audio_enabled ){
        return update_tilt_state_alt(dev);
    }
    #endif
    
    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);
	if (ret != 10) {
		FN_ERROR("Error in accelerometer reading, libusb_control_transfer returned %d\n", ret);
		return ret < 0 ? ret : -1;
	}

	ux = ((uint16_t)buf[2] << 8) | buf[3];
	uy = ((uint16_t)buf[4] << 8) | buf[5];
	uz = ((uint16_t)buf[6] << 8) | buf[7];

	dev->raw_state.accelerometer_x = (int16_t)ux;
	dev->raw_state.accelerometer_y = (int16_t)uy;
	dev->raw_state.accelerometer_z = (int16_t)uz;
	dev->raw_state.tilt_angle = (int8_t)buf[8];
	dev->raw_state.tilt_status = (freenect_tilt_status_code)buf[9];

	return ret;
}
Exemple #5
0
int freenect_set_tilt_degs_alt(freenect_device *dev, int tilt_degrees)
{
	freenect_context *ctx = dev->parent;

	if (tilt_degrees > 31 || tilt_degrees < -31) {
		FN_WARNING("set_tilt(): degrees %d out of safe range [-31, 31]\n", tilt_degrees);
		return -1;
	}
    
	fn_alt_motor_command cmd;
	cmd.magic = fn_le32(0x06022009);
	cmd.tag = fn_le32(tag_seq++);
	cmd.arg1 = fn_le32(0);
	cmd.cmd = fn_le32(0x803b);
	cmd.arg2 = (uint32_t)(fn_le32((int32_t)tilt_degrees));
	int transferred = 0;
	int res = 0;
	unsigned char buffer[20];
	memcpy(buffer, &cmd, 20);

	res = libusb_bulk_transfer(dev->usb_audio.dev, 0x01, buffer, 20, &transferred, 250);
	if (res != 0) {
		FN_ERROR("freenect_set_tilt_alt(): libusb_bulk_transfer failed: %d (transferred = %d)\n", res, transferred);
		return res;
	}
    
	return get_reply(dev->usb_audio.dev, ctx);
}
Exemple #6
0
FN_INTERNAL int fnusb_claim_camera(freenect_device* dev)
{
	freenect_context *ctx = dev->parent;

	int ret = 0;

#ifndef _WIN32 // todo: necessary?
	// Detach an existing kernel driver for the device
	ret = libusb_kernel_driver_active(dev->usb_cam.dev, 0);
	if (ret == 1)
	{
		ret = libusb_detach_kernel_driver(dev->usb_cam.dev, 0);
		if (ret < 0)
		{
			FN_ERROR("Failed to detach camera kernel driver: %s\n", libusb_error_name(ret));
			libusb_close(dev->usb_cam.dev);
			dev->usb_cam.dev = NULL;
			return ret;
		}
	}
#endif

	ret = libusb_claim_interface(dev->usb_cam.dev, 0);
	if (ret < 0)
	{
		FN_ERROR("Failed to claim camera interface: %s\n", libusb_error_name(ret));
		libusb_close(dev->usb_cam.dev);
		dev->usb_cam.dev = NULL;
		return ret;
	}

	if (dev->usb_cam.PID == PID_K4W_CAMERA)
	{
		ret = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1);
		if (ret != 0)
		{
			FN_ERROR("Failed to set alternate interface #1 for K4W: %s\n", libusb_error_name(ret));
			libusb_close(dev->usb_cam.dev);
			dev->usb_cam.dev = NULL;
			return ret;
		}
	}

	return ret;
}
static void iso_callback(struct libusb_transfer *xfer)
{
	int i;
	fnusb_isoc_stream *strm = (fnusb_isoc_stream*)xfer->user_data;

	if (strm->dead) {
		freenect_context *ctx = strm->parent->parent->parent;
		strm->dead_xfers++;
		FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers);
		return;
	}

	switch(xfer->status) {
		case LIBUSB_TRANSFER_COMPLETED: // Normal operation.
		{
			uint8_t *buf = (uint8_t*)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);
			break;
		}
		case LIBUSB_TRANSFER_NO_DEVICE:
		{
			// We lost the device we were talking to.  This is a large problem,
			// and one that we should eventually come up with a way to
			// properly propagate up to the caller.
			freenect_context *ctx = strm->parent->parent->parent;
			FN_ERROR("USB device disappeared, cancelling stream :(\n");
			strm->dead_xfers++;
			fnusb_stop_iso(strm->parent, strm);
			break;
		}
		case LIBUSB_TRANSFER_CANCELLED:
		{
			freenect_context *ctx = strm->parent->parent->parent;
			FN_SPEW("EP %02x transfer cancelled\n", xfer->endpoint);
			strm->dead_xfers++;
			break;
		}
		default:
		{
			// On other errors, resubmit the transfer - in particular, libusb
			// on OSX tends to hit random errors a lot.  If we don't resubmit
			// the transfers, eventually all of them die and then we don't get
			// any more data from the Kinect.
			freenect_context *ctx = strm->parent->parent->parent;
			FN_WARNING("Isochronous transfer error: %d\n", xfer->status);
			libusb_submit_transfer(xfer);
			break;
		}
	}
}
Exemple #8
0
static int check_version_string(fnusb_dev* dev) {
	freenect_context* ctx = dev->parent->parent;
	bootloader_command bootcmd;
	memset(&bootcmd, 0, sizeof(bootcmd));
	bootcmd.magic = fn_le32(0x06022009);
	bootcmd.tag   = fn_le32(dev->parent->audio_tag);
	bootcmd.bytes = fn_le32(0x60);
	bootcmd.cmd   = fn_le32(0);
	bootcmd.addr  = fn_le32(0x15);
	unsigned char buffer[512];
	int res;
	int transferred;

	FN_INFO("check_version_string(): About to send: ");
	dump_bl_cmd(ctx, bootcmd);

	// Send "get version string" command
	res = fnusb_bulk(dev, 1, (unsigned char*)&bootcmd, sizeof(bootcmd), &transferred);
	if(res != 0 || transferred != sizeof(bootcmd)) {
		FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)sizeof(bootcmd));
		return -1;
	}

	// Read version string reply
	res = fnusb_bulk(dev, 0x81, buffer, 512, &transferred);
	if(res != 0 ) {
		FN_ERROR("Error reading version string: %d\ttransferred: %d (expected %d)\n", res, transferred, 0x60);
		return res;
	}
	FN_INFO("Read version string: ");
	int i;
	for(i = 0; i < transferred; ++i) {
		FN_INFO("%02X ", buffer[i]);
	}
	FN_INFO("\n");

	// Read status code reply
	res = get_reply(dev);
	dev->parent->audio_tag++;
	return res;
}
Exemple #9
0
	void InsertRecord()
	{
		FN_TRACE();
		try
		{
			otl_nocommit_stream cStat(1, "insert into user(id, name) values(7, 'shi77')", m_sConn);
		}
		catch (otl_exception& e)
		{
			FN_ERROR("?, ?, ?, ?") << (char*)e.msg << e.stm_text << (char*)e.sqlstate << e.var_info;
		}
	}
Exemple #10
0
	void CreateTable()
	{
		FN_TRACE();
		try
		{
			otl_nocommit_stream cStat(1, "drop table if exists user", m_sConn);
			otl_nocommit_stream cStat2(1, "create table user(id bigint(18), name varchar(64))", m_sConn);
		}
		catch (otl_exception& e)
		{
			FN_ERROR("?, ?, ?, ?") << (char*)e.msg << e.stm_text << (char*)e.sqlstate << e.var_info;
		}
	}
Exemple #11
0
FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial)
{
	// This is implemented by listing the devices and seeing which index (if
	// any) has a camera with a matching serial number, and then punting to
	// freenect_open_device with that index.
	struct freenect_device_attributes* attrlist;
	struct freenect_device_attributes* item;
	int count = fnusb_list_device_attributes(&ctx->usb, &attrlist);
	if (count < 0) {
		FN_ERROR("freenect_open_device_by_camera_serial: Couldn't enumerate serial numbers\n");
		return -1;
	}
	int index = 0;
	for(item = attrlist ; item != NULL; item = item->next , index++) {
		if (strlen(item->camera_serial) == strlen(camera_serial) && strcmp(item->camera_serial, camera_serial) == 0) {
			freenect_free_device_attributes(attrlist);
			return freenect_open_device(ctx, dev, index);
		}
	}
	freenect_free_device_attributes(attrlist);
	FN_ERROR("freenect_open_device_by_camera_serial: Couldn't find a device with serial %s\n", camera_serial);
	return -1;
}
Exemple #12
0
FREENECTAPI int freenect_close_device(freenect_device *dev)
{
	freenect_context *ctx = dev->parent;
	int res;

	// stop streams, if active
	freenect_stop_depth(dev);
	freenect_stop_video(dev);

	res = fnusb_close_subdevices(dev);
	if (res < 0) {
		FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
		return res;
	}

	freenect_device *last = NULL;
	freenect_device *cur = ctx->first;

	while (cur && cur != dev) {
		last = cur;
		cur = cur->next;
	}

	if (!cur) {
		FN_ERROR("device %p not found in linked list for this context!\n", dev);
		return -1;
	}

	if (last)
		last->next = cur->next;
	else
		ctx->first = cur->next;

	free(dev);
	return 0;
}
Exemple #13
0
FREENECTAPI int freenect_close_device(freenect_device *dev)
{
	freenect_context *ctx = dev->parent;
	int res;

	if (dev->usb_cam.dev) {
		freenect_camera_teardown(dev);
	}

	res = fnusb_close_subdevices(dev);
	if (res < 0) {
		FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
		return res;
	}

	freenect_device *last = NULL;
	freenect_device *cur = ctx->first;

	while (cur && cur != dev) {
		last = cur;
		cur = cur->next;
	}

	if (!cur) {
		FN_ERROR("device %p not found in linked list for this context!\n", dev);
		return -1;
	}

	if (last)
		last->next = cur->next;
	else
		ctx->first = cur->next;

	free(dev);
	return 0;
}
Exemple #14
0
int freenect_update_tilt_state(freenect_device *dev)
{
	freenect_context *ctx = dev->parent;
	uint8_t buf[10];
	uint16_t ux, uy, uz;
	int ret = fnusb_control(&dev->usb_motor, 0xC0, 0x32, 0x0, 0x0, buf, 10);
	if (ret != 10) {
		FN_ERROR("Error in accelerometer reading, libusb_control_transfer returned %d\n", ret);
		return ret < 0 ? ret : -1;
	}

	ux = ((uint16_t)buf[2] << 8) | buf[3];
	uy = ((uint16_t)buf[4] << 8) | buf[5];
	uz = ((uint16_t)buf[6] << 8) | buf[7];

	dev->raw_state.accelerometer_x = (int16_t)ux;
	dev->raw_state.accelerometer_y = (int16_t)uy;
	dev->raw_state.accelerometer_z = (int16_t)uz;
	dev->raw_state.tilt_angle = (int8_t)buf[8];
	dev->raw_state.tilt_status = (freenect_tilt_status_code)buf[9];

	return ret;
}
Exemple #15
0
	void SelectRecord()
	{
		FN_TRACE();
		try
		{
			otl_nocommit_stream cStat(1, "select * from user", m_sConn);
			int nId;
			char szUser[64];
			for (;;)
			{
				const bool bHasNext = cStat >> nId >> szUser;
				if (!bHasNext)
				{
					break;
				}
				FN_INFO("?, ?") << nId << szUser;
			}
		}
		catch (otl_exception& e)
		{
			FN_ERROR("?, ?, ?, ?") << (char*)e.msg << e.stm_text << (char*)e.sqlstate << e.var_info;
		}
	}
Exemple #16
0
FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index)
{
	int res;
	freenect_device *pdev = (freenect_device*)malloc(sizeof(freenect_device));
	if (!pdev){
		__android_log_write(ANDROID_LOG_INFO, "Kinect","freenect_open_device: malloc failed\n");
		return -1;
	}
	__android_log_write(ANDROID_LOG_INFO, "Kinect","freenect_open_device: malloc successful\n");

	memset(pdev, 0, sizeof(*pdev));

	pdev->parent = ctx;

	res = fnusb_open_subdevices(pdev, index);
	if (res < 0) {
		free(pdev);
		__android_log_write(ANDROID_LOG_INFO, "Kinect","freenect_open_device: fnusb_open_subdevices failed\n");
		return res;
	}
	__android_log_write(ANDROID_LOG_INFO, "Kinect","freenect_open_device: fnusb_open_subdevices successed\n");

#ifdef BUILD_AUDIO
	if (pdev->usb_audio.dev) {
		res = fnusb_num_interfaces(&pdev->usb_audio);
		if (res == 1) {
			// Upload audio firmware, release devices, and reopen them
			res = upload_firmware(&pdev->usb_audio);
			if (res < 0) {
				FN_ERROR("upload_firmware failed: %d\n", res);
				free(pdev);
				return res;
			}

			res = fnusb_close_subdevices(pdev);
			if (res < 0) {
				FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
				free(pdev);
				return res;
			}
			sleep(1); // Give time for the device to reenumerate before trying to open it
			res = fnusb_open_subdevices(pdev, index);
			if (res < 0) {
				free(pdev);
				return res;
			}
		}
	}
#endif

	if (!ctx->first) {
		ctx->first = pdev;
	} else {
		freenect_device *prev = ctx->first;
		while (prev->next)
			prev = prev->next;
		prev->next = pdev;
	}

	*dev = pdev;
	return 0;
}
Exemple #17
0
int freenect_close_device(freenect_device *dev)
{
	freenect_context *ctx = dev->parent;
	FN_ERROR("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
	return 0;
}
Exemple #18
0
int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;

	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;

	int i = 0, nr_cam = 0, nr_mot = 0;
	int res;
	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 != VID_MICROSOFT)
			continue;

		// Search for the camera
		if (!dev->usb_cam.dev && desc.idProduct == PID_NUI_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);
				if (res < 0 || !dev->usb_cam.dev) {
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_cam.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on camera: %d\n", res);
					libusb_close(dev->usb_cam.dev);
					dev->usb_cam.dev = NULL;
					break;
				}
			} else {
				nr_cam++;
			}
		}

		// Search for the motor
		if (!dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) {
			// If the index given by the user matches our camera index
			if (nr_mot == index) {
				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev) {
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			} else {
				nr_mot++;
			}
		}
	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	if (dev->usb_cam.dev && dev->usb_motor.dev) {
		return 0;
	} else {
		if (dev->usb_cam.dev) {
			libusb_release_interface(dev->usb_cam.dev, 0);
			libusb_close(dev->usb_cam.dev);
		}
		if (dev->usb_motor.dev) {
			libusb_release_interface(dev->usb_motor.dev, 0);
			libusb_close(dev->usb_motor.dev);
		}
		return -1;
	}
}
Exemple #19
0
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;

	/* Search for firmware file (audios.bin) in the following places:
	 * $LIBFREENECT_FIRMWARE_PATH
	 * .
	 * ${HOME}/.libfreenect
	 * /usr/local/share/libfreenect
	 * /usr/share/libfreenect
	 */
	const char* fw_filename = "/audios.bin";
	int filenamelen = strlen(fw_filename);
	int i;
	int searchpathcount;
	FILE* fw = NULL;
	for(i = 0, searchpathcount = 5; !fw && i < searchpathcount; i++) {
		char* fwfile;
		int needs_free = 0;
		switch(i) {
			case 0: {
				char* envpath = getenv("LIBFREENECT_FIRMWARE_PATH");
				if (!envpath)
					continue;
				int pathlen = strlen(envpath);
				fwfile = malloc(pathlen + filenamelen + 1);
				strcpy(fwfile, envpath);
				strcat(fwfile, fw_filename);
				needs_free = 1;
				}
				break;
			case 1:
				fwfile = "./audios.bin";
				break;
			case 2: {
				// Construct $HOME/.libfreenect/
				char* home = getenv("HOME");
				if (!home)
					continue;
				int homelen = strlen(home);
				char* dotfolder = "/.libfreenect";
				int locallen = strlen(dotfolder);
				fwfile = (char*)malloc(homelen + locallen + filenamelen + 1);
				strcpy(fwfile, home);
				strcat(fwfile, dotfolder);
				strcat(fwfile, fw_filename);
				needs_free = 1;
				}
				break;
			case 3:
				fwfile = "/usr/local/share/libfreenect/audios.bin";
				break;
			case 4:
				fwfile = "/usr/share/libfreenect/audios.bin";
				break;
			default: break;
		}
		FN_INFO("Trying to open %s as firmware...\n", fwfile);
		fw = fopen(fwfile, "rb");
		if (needs_free) {
			free(fwfile);
		}
	}
	if (!fw) {
		FN_ERROR("upload_firmware: failed to find firmware file.\n");
		return -errno;
	}
	// Now we have an open firmware file handle.
	uint32_t addr = 0x00080000;
	int read;
	unsigned char page[0x4000];
	do {
		read = fread(page, 1, 0x4000, fw);
		if(read <= 0) {
			break;
		}
		bootcmd.tag = fn_le32(dev->parent->audio_tag);
		bootcmd.bytes = fn_le32(read);
		bootcmd.cmd = fn_le32(0x03);
		bootcmd.addr = fn_le32(addr);
		FN_INFO("About to send: ");
		dump_bl_cmd(ctx, bootcmd);
		// Send it off!
		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;
		while(bytes_sent < read) {
			int to_send = (read - bytes_sent > 512 ? 512 : read - bytes_sent);
			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;
		}
		res = get_reply(dev);
		addr += (uint32_t)read;
		dev->parent->audio_tag++;
	} while (read > 0);
	fclose(fw);
	fw = NULL;

	bootcmd.tag   = fn_le32(dev->parent->audio_tag);
	bootcmd.bytes = fn_le32(0);
	bootcmd.cmd   = fn_le32(0x04);
	bootcmd.addr  = fn_le32(0x00080030);
	dump_bl_cmd(ctx, bootcmd);
	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));
		return -1;
	}
	res = get_reply(dev);
	dev->parent->audio_tag++;
	FN_INFO("Firmware successfully uploaded and launched.  Device will disconnect and reenumerate.\n");
	return 0;
}
int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;
#ifdef BUILD_AUDIO
	dev->usb_audio.parent = dev;
	dev->usb_audio.dev = NULL;
#endif

	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;

	int i = 0, nr_cam = 0, nr_mot = 0;
#ifdef BUILD_AUDIO
	int nr_audio = 0;
#endif
	int res;
	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 != VID_MICROSOFT)
			continue;

		// Search for the camera
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && desc.idProduct == PID_NUI_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);
				if (res < 0 || !dev->usb_cam.dev) {
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}
#ifndef _WIN32
				// Detach an existing kernel driver for the device
				res = libusb_kernel_driver_active(dev->usb_cam.dev, 0);
				if (res == 1) {
					res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0);
					if (res < 0) {
						FN_ERROR("Could not detach kernel driver for camera: %d\n", res);
						libusb_close(dev->usb_cam.dev);
						dev->usb_cam.dev = NULL;
						break;
					}
				}
#endif
				res = libusb_claim_interface (dev->usb_cam.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on camera: %d\n", res);
					libusb_close(dev->usb_cam.dev);
					dev->usb_cam.dev = NULL;
					break;
				}
			} else {
				nr_cam++;
			}
		}

		// Search for the motor
		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) {
				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev) {
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			} else {
				nr_mot++;
			}
		}

#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 the index given by the user matches our audio index
			if (nr_audio == index) {
				res = libusb_open (devs[i], &dev->usb_audio.dev);
				if (res < 0 || !dev->usb_audio.dev) {
					FN_ERROR("Could not open audio: %d\n", res);
					dev->usb_audio.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_audio.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on audio: %d\n", res);
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					break;
				}
				// Using the device handle that we've claimed, see if this
				// device has already uploaded firmware (has 2 interfaces).  If
				// not, save the serial number (by reading the appropriate
				// descriptor), upload the firmware, and then enter a loop
				// waiting for a device with the same serial number to
				// reappear.
				int num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
				if (num_interfaces == 1) {
					// Read the serial number from the string descriptor and save it.
					unsigned char string_desc[256]; // String descriptors are at most 256 bytes
					res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256);
					if (res < 0) {
						FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n");
						break;
					}
					char* audio_serial = strdup((char*)string_desc);

					FN_SPEW("Uploading firmware to audio device in bootloader state.\n");
					res = upload_firmware(&dev->usb_audio);
					if (res < 0) {
						FN_ERROR("upload_firmware failed: %d\n", res);
						break;
					}
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					// Wait for the device to reappear.
					int loops = 0;
					for (loops = 0; loops < 10; loops++) { // Loop for at most 10 tries.
						FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial);
						// Scan devices.
						libusb_device **new_dev_list;
						int dev_index;
						ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list);
						for (dev_index = 0; dev_index < num_new_devs; ++dev_index) {
							struct libusb_device_descriptor new_dev_desc;
							int r;
							r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc);
							if (r < 0)
								continue;
							// If this dev is a Kinect audio device, open device, read serial, and compare.
							if (new_dev_desc.idVendor == VID_MICROSOFT && new_dev_desc.idProduct == PID_NUI_AUDIO) {
								FN_SPEW("Matched VID/PID!\n");
								libusb_device_handle* new_dev_handle;
								// Open device
								r = libusb_open(new_dev_list[dev_index], &new_dev_handle);
								if (r < 0)
									continue;
								// Read serial
								r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256);
								if (r < 0) {
									FN_SPEW("Lost new audio device while fetching serial number.\n");
									libusb_close(new_dev_handle);
									continue;
								}
								// Compare to expected serial
								if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) {
									// We found it!
									r = libusb_claim_interface(new_dev_handle, 0);
									if (r != 0) {
										// Ouch, found the device but couldn't claim the interface.
										FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial);
										libusb_close(new_dev_handle);
										continue;
									}
									// Save the device handle.
									dev->usb_audio.dev = new_dev_handle;
									// Verify that we've actually found a device running the right firmware.
									if (fnusb_num_interfaces(&dev->usb_audio) != 2) {
										FN_SPEW("Opened audio with matching serial but too few interfaces.\n");
										dev->usb_audio.dev = NULL;
										libusb_close(new_dev_handle);
										continue;
									}
									break;
								} else {
									FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial);
								}
							}
						}

						libusb_free_device_list(new_dev_list, 1);
						// If we found the right device, break out of this loop.
						if (dev->usb_audio.dev)
							break;
						// Sleep for a second to give the device more time to reenumerate.
						sleep(1);
					}
					free(audio_serial);
				}
			} else {
				nr_audio++;
			}
		}
#endif

	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	// Check that each subdevice is either opened or not enabled.
	if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
		&& (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))
#ifdef BUILD_AUDIO
		&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))
#endif
		) {
		return 0;
	} else {
		if (dev->usb_cam.dev) {
			libusb_release_interface(dev->usb_cam.dev, 0);
			libusb_close(dev->usb_cam.dev);
		}
		if (dev->usb_motor.dev) {
			libusb_release_interface(dev->usb_motor.dev, 0);
			libusb_close(dev->usb_motor.dev);
		}
#ifdef BUILD_AUDIO
		if (dev->usb_audio.dev) {
			libusb_release_interface(dev->usb_audio.dev, 0);
			libusb_close(dev->usb_audio.dev);
		}
#endif
		return -1;
	}
}
static void iso_callback(struct libusb_transfer *xfer)
{
	int i;
	fnusb_isoc_stream *strm = (fnusb_isoc_stream*)xfer->user_data;
	freenect_context *ctx = strm->parent->parent->parent;

	if (strm->dead) {
		strm->dead_xfers++;
		FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers);
		return;
	}

	switch(xfer->status) {
		case LIBUSB_TRANSFER_COMPLETED: // Normal operation.
		{
			uint8_t *buf = (uint8_t*)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;
			}
			int res;
			res = libusb_submit_transfer(xfer);
			if (res != 0) {
				FN_ERROR("iso_callback(): failed to resubmit transfer after successful completion: %d\n", res);
				strm->dead_xfers++;
				if (res == LIBUSB_ERROR_NO_DEVICE) {
					strm->parent->device_dead = 1;
				}
			}
			break;
		}
		case LIBUSB_TRANSFER_NO_DEVICE:
		{
			// We lost the device we were talking to.  This is a large problem,
			// and one that we should eventually come up with a way to
			// properly propagate up to the caller.
			if(!strm->parent->device_dead) {
				FN_ERROR("USB device disappeared, cancelling stream %02x :(\n", xfer->endpoint);
			}
			strm->dead_xfers++;
			strm->parent->device_dead = 1;
			break;
		}
		case LIBUSB_TRANSFER_CANCELLED:
		{
			if(strm->dead) {
				FN_SPEW("EP %02x transfer cancelled\n", xfer->endpoint);
			} else {
				// This seems to be a libusb bug on OSX - instead of completing
				// the transfer with LIBUSB_TRANSFER_NO_DEVICE, the transfers
				// simply come back cancelled by the OS.  We can detect this,
				// though - the stream should be marked dead if we're
				// intentionally cancelling transfers.
				if(!strm->parent->device_dead) {
					FN_ERROR("Got cancelled transfer, but we didn't request it - device disconnected?\n");
				}
				strm->parent->device_dead = 1;
			}
			strm->dead_xfers++;
			break;
		}
		default:
		{
			// On other errors, resubmit the transfer - in particular, libusb
			// on OSX tends to hit random errors a lot.  If we don't resubmit
			// the transfers, eventually all of them die and then we don't get
			// any more data from the Kinect.
			FN_WARNING("Isochronous transfer error: %d\n", xfer->status);
			int res;
			res = libusb_submit_transfer(xfer);
			if (res != 0) {
				FN_ERROR("Isochronous transfer resubmission failed after unknown error: %d\n", res);
				strm->dead_xfers++;
				if (res == LIBUSB_ERROR_NO_DEVICE) {
					strm->parent->device_dead = 1;
				}
			}
			break;
		}
	}
}
FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

    dev->device_does_motor_control_with_audio = 0;
    dev->motor_control_with_audio_enabled = 0;
    
	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;
#ifdef BUILD_AUDIO
	dev->usb_audio.parent = dev;
	dev->usb_audio.dev = NULL;
#endif

	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;

	int i = 0, nr_cam = 0, nr_mot = 0;
#ifdef BUILD_AUDIO
	int nr_audio = 0;
#endif
	int res;
	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 != 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 || 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);
				if (res < 0 || !dev->usb_cam.dev) {
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}
				if (desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)) {
					freenect_device_flags requested_devices = ctx->enabled_subdevices;
					
					// Not the old kinect so we only set up the camera
					ctx->enabled_subdevices = FREENECT_DEVICE_CAMERA;
					ctx->zero_plane_res = 334;
                    dev->device_does_motor_control_with_audio = 1;

                    //lets also set the LED ON
                    //this keeps the camera alive for some systems which get freezes
                    if( desc.idProduct == PID_K4W_CAMERA ){
                        freenect_extra_keep_alive(PID_K4W_AUDIO);
                    }else{
                        freenect_extra_keep_alive(PID_NUI_AUDIO);
                    }
                    
#ifdef BUILD_AUDIO
                    //for newer devices we need to enable the audio device for motor control
					//we only do this though if motor has been requested.
                    if ((requested_devices & FREENECT_DEVICE_MOTOR) && (requested_devices & FREENECT_DEVICE_AUDIO) == 0)
                    {
                        ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices | FREENECT_DEVICE_AUDIO);
                    }
#endif
                    
				}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);
				if (res == 1) {
					res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0);
					if (res < 0) {
						FN_ERROR("Could not detach kernel driver for camera: %d\n", res);
						libusb_close(dev->usb_cam.dev);
						dev->usb_cam.dev = NULL;
						break;
					}
				}
#endif
				res = libusb_claim_interface (dev->usb_cam.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on camera: %d\n", res);
					libusb_close(dev->usb_cam.dev);
					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) {
				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev) {
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			} else {
				nr_mot++;
			}
		}

#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 || fnusb_is_pid_k4w_audio(desc.idProduct))) {
			// If the index given by the user matches our audio index
            
			if (nr_audio == index) {
				res = libusb_open (devs[i], &dev->usb_audio.dev);
				if (res < 0 || !dev->usb_audio.dev) {
					FN_ERROR("Could not open audio: %d\n", res);
					dev->usb_audio.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_audio.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on audio: %d\n", res);
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					break;
				}
                
				// Using the device handle that we've claimed, see if this
				// device has already uploaded firmware (has 2 interfaces).  If
				// not, save the serial number (by reading the appropriate
				// descriptor), upload the firmware, and then enter a loop
				// waiting for a device with the same serial number to
				// reappear.
				int num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
                
                if( num_interfaces >= 2 ){
                    if( dev->device_does_motor_control_with_audio ){
                        dev->motor_control_with_audio_enabled = 1;
                    }
                }else{
                
					// Read the serial number from the string descriptor and save it.
					unsigned char string_desc[256]; // String descriptors are at most 256 bytes
					res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256);
					if (res < 0) {
						FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n");
						break;
					}
					char* audio_serial = strdup((char*)string_desc);
                
					FN_SPEW("Uploading firmware to audio device in bootloader state.\n");
                    
                    // Check if we can load from memory - otherwise load from disk 
                    if( desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0){
                        FN_SPEW("loading firmware from memory\n");
                        res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size);
                    }
                    else if( desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0 ){
                        FN_SPEW("loading firmware from memory\n");
                        res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size);
                    }
                    else{
                        res = upload_firmware(&dev->usb_audio, "audios.bin");
                    }
					
                    if (res < 0) {
						FN_ERROR("upload_firmware failed: %d\n", res);
						break;
					}
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					// Wait for the device to reappear.
					int loops = 0;
					for (loops = 0; loops < 10; loops++) { // Loop for at most 10 tries.
						FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial);
						// Scan devices.
						libusb_device **new_dev_list;
						int dev_index;
						ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list);
						for (dev_index = 0; dev_index < num_new_devs; ++dev_index) {
							struct libusb_device_descriptor new_dev_desc;
							int r;
							r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc);
							if (r < 0)
								continue;
							// If this dev is a Kinect audio device, open device, read serial, and compare.
							if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) {
								FN_SPEW("Matched VID/PID!\n");
								libusb_device_handle* new_dev_handle;
								// Open device
								r = libusb_open(new_dev_list[dev_index], &new_dev_handle);
								if (r < 0)
									continue;
								// Read serial
								r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256);
								if (r < 0) {
									FN_SPEW("Lost new audio device while fetching serial number.\n");
									libusb_close(new_dev_handle);
									continue;
								}
								// Compare to expected serial
								if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) {
									// We found it!
									r = libusb_claim_interface(new_dev_handle, 0);
									if (r != 0) {
										// Ouch, found the device but couldn't claim the interface.
										FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial);
										libusb_close(new_dev_handle);
										continue;
									}
									// Save the device handle.
									dev->usb_audio.dev = new_dev_handle;
									
                                    // Verify that we've actually found a device running the right firmware.
									num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
                                    
                                    if( num_interfaces >= 2 ){
                                        if( dev->device_does_motor_control_with_audio ){
                                            dev->motor_control_with_audio_enabled = 1;
                                        }
                                    }else{
                                        FN_SPEW("Opened audio with matching serial but too few interfaces.\n");
										dev->usb_audio.dev = NULL;
										libusb_close(new_dev_handle);
										continue;
									}									break;
								} else {
									FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial);
								}
							}
						}

						libusb_free_device_list(new_dev_list, 1);
						// If we found the right device, break out of this loop.
						if (dev->usb_audio.dev)
							break;
						// Sleep for a second to give the device more time to reenumerate.
						sleep(1);
					}
					free(audio_serial);
				}
			} else {
				nr_audio++;
			}
		}
#endif

	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	// Check that each subdevice is either opened or not enabled.
	if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
		&& (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))
#ifdef BUILD_AUDIO
		&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))
#endif
		) {
		return 0;
	} else {
		if (dev->usb_cam.dev) {
			libusb_release_interface(dev->usb_cam.dev, 0);
			libusb_close(dev->usb_cam.dev);
		} else {
			FN_ERROR("Failed to open camera subdevice or it is not disabled.");
		}

		if (dev->usb_motor.dev) {
			libusb_release_interface(dev->usb_motor.dev, 0);
			libusb_close(dev->usb_motor.dev);
		} else {
			FN_ERROR("Failed to open motor subddevice or it is not disabled.");
		}

#ifdef BUILD_AUDIO
		if (dev->usb_audio.dev) {
			libusb_release_interface(dev->usb_audio.dev, 0);
			libusb_close(dev->usb_audio.dev);
		} else {
			FN_ERROR("Failed to open audio subdevice or it is not disabled.");
		}
#endif
		return -1;
	}
}
Exemple #23
0
FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

	dev->device_does_motor_control_with_audio = 0;
	dev->motor_control_with_audio_enabled = 0;
    
	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;
	dev->usb_audio.parent = dev;
	dev->usb_audio.dev = NULL;

	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;

	int i = 0, nr_cam = 0, nr_mot = 0;
	int nr_audio = 0;
	int res;
	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 != 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 || desc.idProduct == PID_K4W_CAMERA))
		{
			// If the index given by the user matches our camera index
			if (nr_cam == index)
			{
				dev->usb_cam.VID = desc.idVendor;
				dev->usb_cam.PID = desc.idProduct;

				res = libusb_open (devs[i], &dev->usb_cam.dev);
				if (res < 0 || !dev->usb_cam.dev)
				{
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}

				if (desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267))
				{
					freenect_device_flags requested_devices = ctx->enabled_subdevices;
        
					// Not the 1414 kinect so remove the motor flag, this should preserve the audio flag if set
					ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices & ~FREENECT_DEVICE_MOTOR);
					
					ctx->zero_plane_res = 334;
					dev->device_does_motor_control_with_audio = 1;

					// set the LED for non 1414 devices to keep the camera alive for some systems which get freezes

					libusb_device * audioDevice = fnusb_find_connected_audio_device(devs[i], devs, cnt);
					if (audioDevice != NULL)
					{
						libusb_device_handle * audioHandle = NULL;
						res = libusb_open(audioDevice, &audioHandle);

						if (res != 0)
						{
							FN_ERROR("Failed to set the LED of K4W or 1473 device: %d\n", res);
						}
						else
						{
							// we need to do this as it is possible that the device was not closed properly in a previous session
							// if we don't do this and the device wasn't closed properly - it can cause infinite hangs on LED and TILT functions
							libusb_reset_device(audioHandle);
							libusb_close(audioHandle);

							res = libusb_open(audioDevice, &audioHandle);
							if (res == 0)
							{
								res = libusb_claim_interface(audioHandle, 0);
								if (res != 0)
								{
									FN_ERROR("Unable to claim interface %d\n", res);
								}
								else
								{
									fnusb_set_led_alt(audioHandle, ctx, LED_GREEN);
									libusb_release_interface(audioHandle, 0);
								}
								libusb_close(audioHandle);
							}
						}
					}
					// for newer devices we need to enable the audio device for motor control
					// we only do this though if motor has been requested.
					if ((requested_devices & FREENECT_DEVICE_MOTOR) && (requested_devices & FREENECT_DEVICE_AUDIO) == 0)
					{
						ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices | FREENECT_DEVICE_AUDIO);
					}
				}
				else
				{
					// The good old kinect that tilts and tweets
					ctx->zero_plane_res = 322;
				}

				res = fnusb_claim_camera(dev);
				if (res < 0)
				{
					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)
			{
				dev->usb_motor.VID = desc.idVendor;
				dev->usb_motor.PID = desc.idProduct;

				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev)
				{
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0)
				{
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			}
			else
			{
				nr_mot++;
			}
		}

		// Search for the audio
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct)))
		{
			// If the index given by the user matches our audio index
			if (nr_audio == index)
			{
				dev->usb_audio.VID = desc.idVendor;
				dev->usb_audio.PID = desc.idProduct;

				res = libusb_open (devs[i], &dev->usb_audio.dev);
				if (res < 0 || !dev->usb_audio.dev)
				{
					FN_ERROR("Could not open audio: %d\n", res);
					dev->usb_audio.dev = NULL;
					break;
				}

				res = libusb_claim_interface (dev->usb_audio.dev, 0);
				if (res < 0)
				{
					FN_ERROR("Could not claim interface on audio: %d\n", res);
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					break;
				}

				// Using the device handle that we've claimed, see if this
				// device has already uploaded firmware (has 2 interfaces).
				// If not, save the serial number (by reading the appropriate
				// descriptor), upload the firmware, and then enter a loop
				// waiting for a device with the same serial number to
				// reappear.
				int num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
                
				if (num_interfaces >= 2)
				{
					if (dev->device_does_motor_control_with_audio)
					{
						dev->motor_control_with_audio_enabled = 1;
					}
				}
				else
				{
					// Read the serial number from the string descriptor and save it.
					unsigned char string_desc[256]; // String descriptors are at most 256 bytes
					res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256);
					if (res < 0)
					{
						FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n");
						break;
					}
					char* audio_serial = strdup((char*)string_desc);
                
					FN_SPEW("Uploading firmware to audio device in bootloader state.\n");
                    
					// Check if we can load from memory - otherwise load from disk
					if (desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0)
					{
						FN_SPEW("loading firmware from memory\n");
						res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size);
					}
					else if (desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0)
					{
						FN_SPEW("loading firmware from memory\n");
						res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size);
					}
					else
					{
						res = upload_firmware(&dev->usb_audio, "audios.bin");
					}

					if (res < 0)
					{
						FN_ERROR("upload_firmware failed: %d\n", res);
						break;
					}
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					// Wait for the device to reappear.
					int loops = 0;
					for (loops = 0; loops < 10; loops++)
					{
						FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial);
						// Scan devices.
						libusb_device **new_dev_list;
						int dev_index;
						ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list);
						for (dev_index = 0; dev_index < num_new_devs; ++dev_index)
						{
							struct libusb_device_descriptor new_dev_desc;
							int r;
							r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc);
							if (r < 0)
								continue;
							// If this dev is a Kinect audio device, open device, read serial, and compare.
							if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct)))
							{
								FN_SPEW("Matched VID/PID!\n");
								libusb_device_handle* new_dev_handle;
								// Open device
								r = libusb_open(new_dev_list[dev_index], &new_dev_handle);
								if (r < 0)
									continue;
								// Read serial
								r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256);
								if (r < 0)
								{
									FN_SPEW("Lost new audio device while fetching serial number.\n");
									libusb_close(new_dev_handle);
									continue;
								}
								// Compare to expected serial
								if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0)
								{
									// We found it!
									r = libusb_claim_interface(new_dev_handle, 0);
									if (r != 0)
									{
										// Ouch, found the device but couldn't claim the interface.
										FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial);
										libusb_close(new_dev_handle);
										continue;
									}
									// Save the device handle.
									dev->usb_audio.dev = new_dev_handle;

									// Verify that we've actually found a device running the right firmware.
									num_interfaces = fnusb_num_interfaces(&dev->usb_audio);

									if (num_interfaces >= 2)
									{
										if (dev->device_does_motor_control_with_audio)
										{
											dev->motor_control_with_audio_enabled = 1;
										}
									}
									else
									{
										FN_SPEW("Opened audio with matching serial but too few interfaces.\n");
										dev->usb_audio.dev = NULL;
										libusb_close(new_dev_handle);
										continue;
									}

									break;
								}
								else
								{
									FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial);
								}
							}
						}

						libusb_free_device_list(new_dev_list, 1);
						// If we found the right device, break out of this loop.
						if (dev->usb_audio.dev)
							break;
						// Sleep for a second to give the device more time to reenumerate.
						sleep(1);
					}
					free(audio_serial);
				}
			}
			else
			{
				nr_audio++;
			}
		}
	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	if ((dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
   && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)))
		//&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO)))
	{
		// Each requested subdevice is open.
		// Except audio, which may fail if firmware is missing (or because it hates us).
		return 0;
	}

	if (dev->usb_cam.dev != NULL)
	{
		libusb_release_interface(dev->usb_cam.dev, 0);
		libusb_close(dev->usb_cam.dev);
	}
	else
	{
		FN_ERROR("Failed to open camera subdevice or it is not disabled.");
	}

	if (dev->usb_motor.dev != NULL)
	{
		libusb_release_interface(dev->usb_motor.dev, 0);
		libusb_close(dev->usb_motor.dev);
	}
	else
	{
		FN_ERROR("Failed to open motor subddevice or it is not disabled.");
	}

	if (dev->usb_audio.dev != NULL)
	{
		libusb_release_interface(dev->usb_audio.dev, 0);
		libusb_close(dev->usb_audio.dev);
	}
	else
	{
		FN_ERROR("Failed to open audio subdevice or it is not disabled.");
	}

	return -1;
}
Exemple #24
0
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;

	/* Search for firmware file (audios.bin) in the following places:
	 * $LIBFREENECT_FIRMWARE_PATH
	 * .
	 * ${HOME}/.libfreenect
	 * /usr/local/share/libfreenect
	 * /usr/share/libfreenect
	 */
	const char* fw_filename = "/audios.bin";
	int filenamelen = strlen(fw_filename);
	int i;
	int searchpathcount;
	FILE* fw = NULL;
	for(i = 0, searchpathcount = 5; !fw && i < searchpathcount; i++) {
		char* fwfile;
		int needs_free = 0;
		switch(i) {
			case 0: {
				char* envpath = getenv("LIBFREENECT_FIRMWARE_PATH");
				if (!envpath)
					continue;
				int pathlen = strlen(envpath);
				fwfile = malloc(pathlen + filenamelen + 1);
				strcpy(fwfile, envpath);
				strcat(fwfile, fw_filename);
				needs_free = 1;
				}
				break;
			case 1:
				fwfile = "./audios.bin";
				break;
			case 2: {
				// Construct $HOME/.libfreenect/
				char* home = getenv("HOME");
				if (!home)
					continue;
				int homelen = strlen(home);
				char* dotfolder = "/.libfreenect";
				int locallen = strlen(dotfolder);
				fwfile = (char*)malloc(homelen + locallen + filenamelen + 1);
				strcpy(fwfile, home);
				strcat(fwfile, dotfolder);
				strcat(fwfile, fw_filename);
				needs_free = 1;
				}
				break;
			case 3:
				fwfile = "/usr/local/share/libfreenect/audios.bin";
				break;
			case 4:
				fwfile = "/usr/share/libfreenect/audios.bin";
				break;
			default: break;
		}
		FN_INFO("Trying to open %s as firmware...\n", fwfile);
		fw = fopen(fwfile, "rb");
		if (needs_free) {
			free(fwfile);
		}
	}
	if (!fw) {
		FN_ERROR("upload_firmware: failed to find firmware file.\n");
		return -errno;
	}
	// Now we have an open firmware file handle.
	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 {
		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;
		}
		bootcmd.tag = fn_le32(dev->parent->audio_tag);
		bootcmd.bytes = fn_le32(read);
		bootcmd.cmd = fn_le32(0x03);
		bootcmd.addr = fn_le32(addr);
		FN_INFO("About to send: ");
		dump_bl_cmd(ctx, bootcmd);
		// Send it off!
		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;
		while(bytes_sent < read) {
			int to_send = (read - bytes_sent > 512 ? 512 : read - bytes_sent);
			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;
			total_bytes_sent += to_send;
		}
		res = get_reply(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;
	}

	bootcmd.tag   = fn_le32(dev->parent->audio_tag);
	bootcmd.bytes = fn_le32(0);
	bootcmd.cmd   = fn_le32(0x04);
	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)) {
		FN_ERROR("upload_firmware(): Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(bootcmd));
		return -1;
	}
	res = get_reply(dev);
	dev->parent->audio_tag++;
	FN_INFO("Firmware successfully uploaded and launched.  Device will disconnect and reenumerate.\n");
	return 0;
}
Exemple #25
0
FN_INTERNAL int upload_cemd_data(fnusb_dev* dev) {
	// Now we upload the CEMD data.
	freenect_context* ctx = dev->parent->parent;
	cemdloader_command cemdcmd;
	memset(&cemdcmd, 0, sizeof(cemdcmd));
	cemdcmd.magic = fn_le32(0x06022009);
	cemdcmd.tag   = fn_le32(dev->parent->audio_tag);
	cemdcmd.arg1  = fn_le32(0);
	cemdcmd.cmd   = fn_le32(0x00000133);
	cemdcmd.arg2  = fn_le32(0x00064014); // This is the length of the CEMD data.
	FN_INFO("Starting CEMD data upload:\n");
	int res;
	int transferred;
	res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred);
	if(res != 0 || transferred != sizeof(cemdcmd)) {
		FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(cemdcmd));
		return -1;
	}
	res = get_reply(dev);
	dev->parent->audio_tag++;

	const char* cemd_filename = "cemd_data.bin";
	FILE* cf = fopen(cemd_filename, "r");
	if(cf == NULL) {
		FN_ERROR("upload_cemd_data: Failed to open %s: error %d", cemd_filename, errno);
		return errno;
	}
	uint32_t addr = 0x00000000;
	int read = 0;
	unsigned char page[0x4000];
	do {
		read = fread(page, 1, 0x4000, cf);
		if(read <= 0) {
			break;
		}
		//LOG("");
		cemdcmd.tag  = fn_le32(dev->parent->audio_tag);
		cemdcmd.arg1 = fn_le32(read);
		cemdcmd.cmd  = fn_le32(0x134);
		cemdcmd.arg2 = fn_le32(addr);
		FN_INFO("About to send: ");
		dump_cemd_cmd(ctx, cemdcmd);
		// Send it off!
		res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred);
		if(res != 0 || transferred != sizeof(cemdcmd)) {
			FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, (int)sizeof(cemdcmd));
			return -1;
		}
		int bytes_sent = 0;
		while(bytes_sent < read) {
			int to_send = (read - bytes_sent > 512 ? 512 : read - bytes_sent);
			res = fnusb_bulk(dev, 1, &page[bytes_sent], to_send, &transferred);
			if(res != 0 || transferred != to_send) {
				FN_ERROR("Error: res: %d\ttransferred: %d (expected %d)\n",res, transferred, to_send);
				return -1;
			}
			bytes_sent += to_send;
		}
		res = get_reply(dev);
		addr += (uint32_t)read;
		dev->parent->audio_tag++;
	} while (read > 0);
	fclose(cf);
	cf = NULL;

	cemdcmd.tag  = fn_le32(dev->parent->audio_tag);
	cemdcmd.arg1 = fn_le32(0); // bytes = 0
	cemdcmd.cmd  = fn_le32(0x135);
	cemdcmd.arg2 = fn_le32(0x00064000); // mimicing the USB logs.  This is the # of bytes of actual CEMD data after the 20-byte CEMD header.
	FN_INFO("Finishing CEMD data upload...\n");
	res = fnusb_bulk(dev, 1, (unsigned char*)&cemdcmd, sizeof(cemdcmd), &transferred);
	if(res != 0 || transferred != sizeof(cemdcmd)) {
		FN_ERROR("upload_cemd_data(): Error: res: %d\ttransferred: %d (expected %d)\n", res, transferred, (int)sizeof(cemdcmd));
		return -1;
	}
	res = get_reply(dev);
	dev->parent->audio_tag++;
	FN_INFO("CEMD data uploaded successfully.\n");
	return 0;
}
FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index)
{
	int res;
	freenect_device *pdev = (freenect_device*)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;
	}
#ifdef BUILD_AUDIO
	if (pdev->usb_audio.dev) {
		res = fnusb_num_interfaces(&pdev->usb_audio);
		if (res == 1) {
			// Upload audio firmware, release devices, and reopen them
			res = upload_firmware(&pdev->usb_audio);
			if (res < 0) {
				FN_ERROR("upload_firmware failed: %d\n", res);
				free(pdev);
				return res;
			}

			res = fnusb_close_subdevices(pdev);
			if (res < 0) {
				FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
				free(pdev);
				return res;
			}
			sleep(1); // Give time for the device to reenumerate before trying to open it
			res = fnusb_open_subdevices(pdev, index);
			if (res < 0) {
				free(pdev);
				return res;
			}
		}
	}
#endif

	if (!ctx->first) {
		ctx->first = pdev;
	} else {
		freenect_device *prev = ctx->first;
		while (prev->next)
			prev = prev->next;
		prev->next = pdev;
	}

	*dev = pdev;

	// Do device-specific initialization
	if (pdev->usb_cam.dev) {
		if (freenect_camera_init(pdev) < 0) {
			return -1;
		}
	}

	return 0;
}
int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;
#ifdef BUILD_AUDIO
	dev->usb_audio.parent = dev;
	dev->usb_audio.dev = NULL;
#endif

	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;

	int i = 0, nr_cam = 0, nr_mot = 0;
#ifdef BUILD_AUDIO
	int nr_audio = 0;
#endif
	int res;
	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 != VID_MICROSOFT)
			continue;

		// Search for the camera
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && desc.idProduct == PID_NUI_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);
				if (res < 0 || !dev->usb_cam.dev) {
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}
#ifndef _WIN32
				// Detach an existing kernel driver for the device
				res = libusb_kernel_driver_active(dev->usb_cam.dev, 0);
				if (res == 1) {
					res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0);
					if (res < 0) {
						FN_ERROR("Could not detach kernel driver for camera: %d\n", res);
						libusb_close(dev->usb_cam.dev);
						dev->usb_cam.dev = NULL;
						break;
					}
				}
#endif
				res = libusb_claim_interface (dev->usb_cam.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on camera: %d\n", res);
					libusb_close(dev->usb_cam.dev);
					dev->usb_cam.dev = NULL;
					break;
				}
			} else {
				nr_cam++;
			}
		}

		// Search for the motor
		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) {
				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev) {
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			} else {
				nr_mot++;
			}
		}

#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 the index given by the user matches our audio index
			if (nr_audio == index) {
				res = libusb_open (devs[i], &dev->usb_audio.dev);
				if (res < 0 || !dev->usb_audio.dev) {
					FN_ERROR("Could not open audio: %d\n", res);
					dev->usb_audio.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_audio.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on audio: %d\n", res);
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					break;
				}
			} else {
				nr_audio++;
			}
		}
#endif

	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	// Check that each subdevice is either opened or not enabled.
	if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
		&& (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))
#ifdef BUILD_AUDIO
		&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))
#endif
		) {
		return 0;
	} else {
		if (dev->usb_cam.dev) {
			libusb_release_interface(dev->usb_cam.dev, 0);
			libusb_close(dev->usb_cam.dev);
		}
		if (dev->usb_motor.dev) {
			libusb_release_interface(dev->usb_motor.dev, 0);
			libusb_close(dev->usb_motor.dev);
		}
#ifdef BUILD_AUDIO
		if (dev->usb_audio.dev) {
			libusb_release_interface(dev->usb_audio.dev, 0);
			libusb_close(dev->usb_audio.dev);
		}
#endif
		return -1;
	}
}
Exemple #28
0
int freenect_shutdown(freenect_context *ctx)
{
	FN_ERROR("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
	return 0;
}