/*
 * Haiku Backend for libusb
 * Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#include "libusbi.h"
#include "haiku_usb_raw.h"

using namespace std;

class USBDevice;
class USBDeviceHandle;
class USBTransfer;

class USBDevice {
public:
						USBDevice(const char *);
	virtual					~USBDevice();
	const char*				Location() const;
	uint8					CountConfigurations() const;
	const usb_device_descriptor*		Descriptor() const;
	const usb_configuration_descriptor*	ConfigurationDescriptor(uint8) const;
	const usb_configuration_descriptor*	ActiveConfiguration() const;
	uint8					EndpointToIndex(uint8) const;
	uint8					EndpointToInterface(uint8) const;
	int					ClaimInterface(uint8);
	int					ReleaseInterface(uint8);
	int					CheckInterfacesFree(uint8);
	void					SetActiveConfiguration(uint8);
	uint8					ActiveConfigurationIndex() const;
	bool					InitCheck();
private:
	int					Initialise();
	unsigned int				fClaimedInterfaces;	// Max Interfaces can be 32. Using a bitmask
	usb_device_descriptor			fDeviceDescriptor;
	unsigned char**				fConfigurationDescriptors;
	uint8					fActiveConfiguration;
	char*					fPath;
	map<uint8,uint8>			fConfigToIndex;
	map<uint8,uint8>*			fEndpointToIndex;
	map<uint8,uint8>*			fEndpointToInterface;
	bool					fInitCheck;
};

class USBDeviceHandle {
public:
				USBDeviceHandle(USBDevice *dev);
	virtual			~USBDeviceHandle();
	int			ClaimInterface(uint8);
	int			ReleaseInterface(uint8);
	int			SetConfiguration(uint8);
	int			SetAltSetting(uint8, uint8);
	int			ClearHalt(uint8);
	status_t		SubmitTransfer(struct usbi_transfer *);
	status_t		CancelTransfer(USBTransfer *);
	bool			InitCheck();
private:
	int			fRawFD;
	static status_t		TransfersThread(void *);
	void			TransfersWorker();
	USBDevice*		fUSBDevice;
	unsigned int		fClaimedInterfaces;
	BList			fTransfers;
	BLocker			fTransfersLock;
	sem_id			fTransfersSem;
	thread_id		fTransfersThread;
	bool			fInitCheck;
};

class USBTransfer {
public:
					USBTransfer(struct usbi_transfer *, USBDevice *);
	virtual				~USBTransfer();
	void				Do(int);
	struct usbi_transfer*		UsbiTransfer();
	void				SetCancelled();
	bool				IsCancelled();
private:
	struct usbi_transfer*		fUsbiTransfer;
	struct libusb_transfer*		fLibusbTransfer;
	USBDevice*			fUSBDevice;
	BLocker				fStatusLock;
	bool				fCancelled;
};

class USBRoster {
public:
			USBRoster();
	virtual		~USBRoster();
	int		Start();
	void		Stop();
private:
	void*		fLooper;
};
