/*
 * $RCSfile: detach.c,v $  $Revision: 1.1 $  $Name:  $
 * $Id: detach.c,v 1.1 2006/02/10 01:31:36 bpaauwe Exp $
 * $Author: bpaauwe $
 * $Date: 2006/02/10 01:31:36 $
 * ----------------------------------------------------------------------------
 *
 *  Copyright (c) Bob Paauwe (2006)
 *
 *  This program 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 program 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.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * ----------------------------------------------------------------------------
 *
 *  Description:
 *
 *  This is a simple program that uses libusb to detach the Insteon
 *  PLC from the kernel HID driver.
 */

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

#define IPLC_VENDOR     0x10bf
#define IPLC_PRODUCT    0x0004


usb_dev_handle *locate_iplc();

main()
{
	struct usb_dev_handle *iplc = NULL;

	usb_set_debug(0);

	/*
	 * Find the USB PLC and clain the interface.  This will also try
	 * to detach any kernel driver that has previously claimed the
	 * device.  Specificlly, the Linux HID driver will claim the PLC
	 * when it's attached since the PLC has a HID class.
	 */
	if ((iplc = locate_iplc()) != NULL) {
		if (usb_detach_kernel_driver_np(iplc, 0) != 0) {
			printf("Error detaching kernel driver.\n");
		}
		usb_close(iplc);
	} else {
		printf("Unable to locate 0x%04x:0x%04x\n", IPLC_VENDOR, IPLC_PRODUCT);
	}
}


/*
 * locate_iplc
 *
 * Scan the USB bus for a device matching the Insteon USB PLC. 
 */
usb_dev_handle *locate_iplc()
{
	struct usb_bus *busses, *bus;
	struct usb_device *dev;
	struct usb_dev_handle *dev_handle = NULL;

	usb_init();
	usb_find_busses();
	usb_find_devices();

	busses = usb_get_busses();

	for (bus = busses; bus; bus = bus->next) {
		for (dev = bus->devices; dev; dev = dev->next) {
			if (!dev_handle && (dev->descriptor.idVendor == IPLC_VENDOR) &&
					(dev->descriptor.idProduct == IPLC_PRODUCT)) {
				/* usb_info(dev); */
				dev_handle = usb_open(dev);
			}
		}
	}
	return dev_handle;
}
