#include "hostlib.h"
#include "usb.h"
#include <stdio.h>
#include <time.h>

#define DO_DEBUG 0 

#if DO_DEBUG
#define DEBUG(x) (printf x)
#else
#define DEBUG(x) (void)0
#endif

static struct usb_device *find_on_bus(struct usb_bus *bus, u_int16_t v, u_int16_t p) {
    struct usb_device *dev = bus->devices;

    DEBUG(("HOSTLIB: try to find device on bus\n"));	
    for(; dev; dev = dev->next) {
	DEBUG(("HOSTLIB: found device %04x, %04x \n",dev->descriptor.idVendor, dev->descriptor.idProduct));
        if(dev->descriptor.idVendor == v && dev->descriptor.idProduct == p) {
            return dev;
        }
    }
    return NULL;
}

static struct usb_device *find_dev(u_int16_t v, u_int16_t p) {
    struct usb_bus *bus = usb_get_busses();
    struct usb_device *dev = NULL;

    DEBUG(("HOSTLIB: try to find busses\n"));
    for(; bus; bus = bus->next) {
	DEBUG(("HOSTLIB: found bus\n"));
        dev = find_on_bus(bus, v, p);
        if(dev) return dev;
    }
    return NULL;
}

void avr_send_command(avr_device_t dev, int cmd, int val) {
    avr_send_command_idx(dev, cmd, val, 0);
}

void avr_send_command_idx(avr_device_t dev, int cmd, int val, int idx) {
    DEBUG(("send_command %d %04x %04x\n", cmd, val, idx));
    usb_control_msg((usb_dev_handle *)dev, USB_TYPE_VENDOR, cmd, val,
                    idx, NULL, 0, 1000);
}


int avr_get_response(avr_device_t dev, int cmd, int val, char *buf, int len) {
    return avr_get_response_idx(dev, cmd, val, 0, buf, len);
}


int avr_get_response_idx(avr_device_t dev, int cmd, int val, int idx,
                     char *buf, int len) {
    DEBUG(("get_response %d %04x %04x", cmd, val, idx));
    int ret = usb_control_msg((usb_dev_handle *)dev,
                    USB_TYPE_VENDOR | USB_ENDPOINT_IN, cmd, val,
                    idx, buf, len, 1000);
    DEBUG((" -> %d  (buf[0] = %02x)\n", ret, (unsigned char)buf[0]));
    return ret;
}

void avr_set_debug(int level) {
    usb_set_debug(level);
}

void avr_close(avr_device_t dev) {
    usb_close((usb_dev_handle*)dev);
}

avr_device_t avr_open(void) {
    struct usb_device *dev;
    usb_dev_handle *devh;

    if(getenv("AVR_DEBUG")) { avr_set_debug(atoi(getenv("AVR_DEBUG"))); }

     DEBUG(("HOSTLIB: usb init...\n"));
    usb_init();
    usb_find_busses();
    usb_find_devices();

     DEBUG(("HOSTLIB: call find_dev\n"));
    dev = find_dev(0x3eb, 0x2);
     if(!dev) return NULL;

    DEBUG(("HOSTLIB: found IGOR USB PLUG\n"));
    devh = usb_open(dev);
    if(usb_claim_interface(devh, 0) < 0) {
	DEBUG(("HOSTLIB: error while usbclaim interface\n"));
        usb_close(devh);
        return NULL;
    }
    DEBUG(("HOSTLIB: is all right!!!\n"));
    return (avr_device_t)devh;
}
