/* Metageek WiSPY LibUSB interface 
 *
 * LibUSB userspace control for the Metageek WiSPY spectrum analyzer
 * http://www.metageek.net/
 *
 * Version 0.1 - demo/PoC
 * Mike Kershaw/Dragorn <dragorn@kismetwireless.net>
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Extra thanks to Ryan Woodings @ Metageek for interface documentation
 */

#include <stdio.h>
#include <usb.h>

/* First-gen firmware */
#define METAGEEK_WISPY1_VID	0x04b4
#define METAGEEK_WISPY1_PID	0x0bad

/* Second-gen firmware */
#define METAGEEK_WISPY2_VID	0x1781
#define METAGEEK_WISPY2_PID	0x083e

#define TIMEOUT 3000
#define WAITINBETWEEN 500000

/* Hid get report from spec */
#define HID_GET_REPORT 0x01
#define HID_RT_FEATURE 0x03

/* Basic device initialize, grabs either version 1 or version 2 */
static struct usb_device *init_wispy_device() {
	struct usb_bus *bus;
	struct usb_device *dev;

	/* Libusb init */
	usb_init();
	usb_find_busses();
	usb_find_devices();

	/* Scan all the devices on all the busses */
	for (bus = usb_busses; bus; bus = bus->next) {
		for (dev = bus->devices; dev; dev = dev->next) {
			if (((dev->descriptor.idVendor == METAGEEK_WISPY1_VID) &&
				 (dev->descriptor.idProduct == METAGEEK_WISPY1_PID)) ||
				((dev->descriptor.idVendor == METAGEEK_WISPY2_VID) &&
				 (dev->descriptor.idProduct == METAGEEK_WISPY2_PID)))
				return dev;
		}
	}

	return NULL;
}

int main(int argc, char *argv[]) {
	struct usb_device *dev;
	struct usb_dev_handle *wispy;
	int arg;
	char buf[8];
	int x;
	struct timeval tm;

	memset(buf, 0, sizeof(char) * 8);

	dev = init_wispy_device();
	if (!dev) {
		printf("Unable to find device.\n");
		return 1;
	}

	/* Open the wispy device */
	wispy = usb_open(dev);
	if (!wispy) {
		printf("Unable to open device\n");
		return 1;
	}

	/* Grab it like a keyboard interface, interface 0 */
	if (usb_claim_interface(wispy, 0) < 0) {
		printf("Unable to claim interface 0.\n");
		return 1;
	}

	while (1) {
		/* Grab a report */
		if (usb_control_msg(wispy, USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
							HID_GET_REPORT, (HID_RT_FEATURE << 8),
							0, buf, 8, TIMEOUT) == 0) {
			printf("Failure in control_msg\n");
			return 1;
		}

		printf("Base: %d Signals: ", 2400 + buf[0]);
		for (x = 1; x < 8; x++) {
			float dbm = ((float) buf[x] * 0.95f) - 61;	
			printf("%d ", (int) dbm);
		}
		printf("\n");

		tm.tv_sec = 0;
		tm.tv_usec = 8000;

		select(0, NULL, NULL, NULL, &tm);
	}

	usb_close(wispy);

	return 0;
}	

