/*
 * Some "cool" distro defines PATH_MAX as 4095 not as ussaly 4096
 * Becouse many members offset of libusb structures depends on
 * PATH_MAX value. This makes not portable binary code which
 * uses libusb structures.
 *
 * So this code does it.
 *
 */

/* $Id: usbw.c 16939 2007-05-29 10:27:28Z mindaugas $ */

#include <stdio.h>

#include <usb.h>

#include "libusbw.h"

#if defined(__linux__)
#include "linux.c"
#elif defined(__APPLE__)
#include "darwin.c"
#endif

#ifndef DEBUG
#define DEBUG	1
#endif /*DEBUG */

#define dprintf(level,format,...)				\
	if (level <= DEBUG)					\
		printf(format,##__VA_ARGS__);

#ifndef DEBUG
#define DEBUG 0
#endif /*DEBUG */

void *
open_device(int vendor, int product, int device, int configuration)
{
	struct usb_device
			*device_ptr = NULL;
	struct usb_dev_handle
			*device_hnd = NULL;
	struct usb_bus	*bus = NULL;
	struct usb_bus	*busses;
	int i;

	usb_init();
	i = usb_find_busses();
	i = usb_find_devices();
	busses = usb_get_busses();

	dprintf(2, "Search\n%04X %04X %04X\n\n", vendor, product, device);
	for (bus = busses; bus; bus = bus->next)
	{
		struct usb_device *dev = NULL;

		for (dev = bus->devices; dev; dev = dev->next)
		{
			dprintf(2, "%04X %04X %04X\n",
					dev->descriptor.idVendor,
					dev->descriptor.idProduct,
					dev->descriptor.bcdDevice);
			if ((dev->descriptor.idVendor == vendor) &&
				(dev->descriptor.idProduct == product) &&
				(dev->descriptor.bcdDevice == device))
			{
				device_ptr = dev;
				goto found;
			}
		}
	}

found:
	if (device_ptr == NULL)
	{
		dprintf(1, "Device not found\n");
		return NULL;
	}

	device_hnd = usb_open(device_ptr);
	if (device_hnd == NULL)
	{
		dprintf(1, "Error opening device\n");
		return NULL;
	}

	i = usb_set_configuration(device_hnd, configuration);

	if (i != 0)
	{
		usb_reset(device_hnd);
		dprintf(1, "Device: /proc/bus/usb/%s/%s or /dev/bus/usb/%s/%s\n",
				bus->dirname, device_ptr->filename, bus->dirname, device_ptr->filename);
		dprintf(1, "Error: usb_set_configuration returns: %d (%s)\n",
				i, usb_strerror());

		return NULL;
	}

	i = usb_claim_interface(device_hnd, 0);
	if (i != 0)
	{
		dprintf(1, "error: usb_claim_interface returns: %d (%s)\n",
				i, usb_strerror());
		return NULL;
	}
	dprintf(3, "found\n");
	return device_hnd;
}
