289 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 * Contains commonly used types and procedures, for HCD handling/initialization
 | 
						|
 * If possible, everything OS specific (IPC, virtual memory...) should be here
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef _HCD_COMMON_H_
 | 
						|
#define _HCD_COMMON_H_
 | 
						|
 | 
						|
#include <ddekit/thread.h>
 | 
						|
#include <ddekit/semaphore.h>
 | 
						|
#include <ddekit/usb.h>
 | 
						|
 | 
						|
#include <minix/usb.h>				/* for setup structures */
 | 
						|
#include <minix/usb_ch9.h>			/* for descriptor structures */
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    USB register handling defines                                          *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Helper type used for register bitwise access */
 | 
						|
#define HCD_BIT(num)				(0x01u << (num))
 | 
						|
 | 
						|
/* Unsigned type that can hold all possible addresses */
 | 
						|
typedef unsigned long				hcd_addr;
 | 
						|
 | 
						|
/* Register types */
 | 
						|
typedef unsigned long				hcd_reg4;
 | 
						|
typedef unsigned short				hcd_reg2;
 | 
						|
typedef unsigned char				hcd_reg1;
 | 
						|
 | 
						|
/* For register dereferencing */
 | 
						|
#define _HCD_REG4 				volatile hcd_reg4 *
 | 
						|
#define _HCD_REG2 				volatile hcd_reg2 *
 | 
						|
#define _HCD_REG1 				volatile hcd_reg1 *
 | 
						|
 | 
						|
/* Scalar address to dereference */
 | 
						|
#define _HCD_ADDR(base, off)			(((hcd_addr)(base))+(off))
 | 
						|
 | 
						|
/* Defines for fixed size register access
 | 
						|
 * May cause unaligned memory access */
 | 
						|
#define HCD_WR4(base, off, val)	(*((_HCD_REG4)_HCD_ADDR(base, off)) = (val))
 | 
						|
#define HCD_WR2(base, off, val)	(*((_HCD_REG2)_HCD_ADDR(base, off)) = (val))
 | 
						|
#define HCD_WR1(base, off, val)	(*((_HCD_REG1)_HCD_ADDR(base, off)) = (val))
 | 
						|
#define HCD_RD4(base, off)	(*((_HCD_REG4)_HCD_ADDR(base, off)))
 | 
						|
#define HCD_RD2(base, off)	(*((_HCD_REG2)_HCD_ADDR(base, off)))
 | 
						|
#define HCD_RD1(base, off)	(*((_HCD_REG1)_HCD_ADDR(base, off)))
 | 
						|
 | 
						|
/* Other useful defines */
 | 
						|
#define HCD_SET(val, bits)	((val)|=(bits))
 | 
						|
#define HCD_CLR(val, bits)	((val)&=~(bits))
 | 
						|
 | 
						|
/* Alignment safe conversion from 'bytes' array to a word */
 | 
						|
#define HCD_8TO32(bytes)	(((bytes)[0])		|		\
 | 
						|
				(((bytes)[1])<<8)	|		\
 | 
						|
				(((bytes)[2])<<16)	|		\
 | 
						|
				(((bytes)[3])<<24))
 | 
						|
 | 
						|
/* Convert type's 'sizeof' to 4-byte words count */
 | 
						|
#define HCD_SIZEOF_TO_4(type)	((sizeof(type)+3)/4)
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    USB descriptor types                                                   *
 | 
						|
 *===========================================================================*/
 | 
						|
typedef usb_descriptor_t			hcd_descriptor;
 | 
						|
typedef usb_device_descriptor_t			hcd_device_descriptor;
 | 
						|
typedef usb_config_descriptor_t			hcd_config_descriptor;
 | 
						|
typedef usb_interface_descriptor_t		hcd_interface_descriptor;
 | 
						|
typedef usb_endpoint_descriptor_t		hcd_endpoint_descriptor;
 | 
						|
typedef usb_string_descriptor_t			hcd_string_descriptor;
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    HCD descriptor tree types                                              *
 | 
						|
 *===========================================================================*/
 | 
						|
typedef struct hcd_endpoint {
 | 
						|
 | 
						|
	hcd_endpoint_descriptor descriptor;
 | 
						|
}
 | 
						|
hcd_endpoint;
 | 
						|
 | 
						|
typedef struct hcd_interface {
 | 
						|
 | 
						|
	hcd_interface_descriptor descriptor;
 | 
						|
	hcd_endpoint * endpoint;
 | 
						|
	int num_endpoints;
 | 
						|
}
 | 
						|
hcd_interface;
 | 
						|
 | 
						|
typedef struct hcd_configuration {
 | 
						|
 | 
						|
	hcd_config_descriptor descriptor;
 | 
						|
	hcd_interface * interface;
 | 
						|
	int num_interfaces;
 | 
						|
}
 | 
						|
hcd_configuration;
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    HCD device helper types                                                *
 | 
						|
 *===========================================================================*/
 | 
						|
typedef					void (*hcd_thread_function)(void *);
 | 
						|
typedef ddekit_thread_t			hcd_thread;
 | 
						|
typedef ddekit_sem_t			hcd_lock;
 | 
						|
typedef struct hcd_driver_state		hcd_driver_state;
 | 
						|
typedef struct ddekit_usb_urb		hcd_urb;
 | 
						|
 | 
						|
typedef enum {
 | 
						|
 | 
						|
	HCD_STATE_DISCONNECTED = 0,		/* default for initialization */
 | 
						|
	HCD_STATE_CONNECTION_PENDING,
 | 
						|
	HCD_STATE_CONNECTED
 | 
						|
}
 | 
						|
hcd_state;
 | 
						|
 | 
						|
typedef enum {
 | 
						|
 | 
						|
	HCD_SPEED_LOW,
 | 
						|
	HCD_SPEED_FULL,
 | 
						|
	HCD_SPEED_HIGH,
 | 
						|
}
 | 
						|
hcd_speed;
 | 
						|
 | 
						|
/* Largest value that can be transfered by this driver at a time
 | 
						|
 * see MAXPAYLOAD in TXMAXP/RXMAXP */
 | 
						|
#define MAX_WTOTALLENGTH 1024
 | 
						|
 | 
						|
typedef struct hcd_device_state {
 | 
						|
 | 
						|
	hcd_driver_state * driver;	/* Specific HCD driver object */
 | 
						|
	hcd_thread * thread;
 | 
						|
	hcd_lock * lock;
 | 
						|
	hcd_urb * urb;
 | 
						|
	void * data;
 | 
						|
 | 
						|
	hcd_device_descriptor device_desc;
 | 
						|
	hcd_configuration config_tree;
 | 
						|
	hcd_reg1 max_packet_size;
 | 
						|
	hcd_speed speed;
 | 
						|
	hcd_state state;
 | 
						|
	int address;
 | 
						|
 | 
						|
	/* Number of bytes received/transmitted in last transfer */
 | 
						|
	int data_len;
 | 
						|
 | 
						|
	/* TODO: forcefully align buffer to make things clear? */
 | 
						|
	/* Buffer for each device to hold transfered data */
 | 
						|
	hcd_reg1 buffer[MAX_WTOTALLENGTH];
 | 
						|
}
 | 
						|
hcd_device_state;
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    HCD event handling                                                     *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Possible USB transfer types */
 | 
						|
typedef enum {
 | 
						|
 | 
						|
	HCD_TRANSFER_CONTROL		= UE_CONTROL,
 | 
						|
	HCD_TRANSFER_ISOCHRONOUS	= UE_ISOCHRONOUS,
 | 
						|
	HCD_TRANSFER_BULK		= UE_BULK,
 | 
						|
	HCD_TRANSFER_INTERRUPT		= UE_INTERRUPT
 | 
						|
}
 | 
						|
hcd_transfer;
 | 
						|
 | 
						|
/* Possible USB transfer directions */
 | 
						|
typedef enum {
 | 
						|
 | 
						|
	HCD_DIRECTION_OUT		= 0,
 | 
						|
	HCD_DIRECTION_IN		= 1,
 | 
						|
	HCD_DIRECTION_UNUSED		= 0xFF
 | 
						|
}
 | 
						|
hcd_direction;
 | 
						|
 | 
						|
/* Possible asynchronous HCD events */
 | 
						|
typedef enum {
 | 
						|
 | 
						|
	HCD_EVENT_CONNECTED,
 | 
						|
	HCD_EVENT_DISCONNECTED,
 | 
						|
	HCD_EVENT_ENDPOINT,
 | 
						|
	HCD_EVENT_URB
 | 
						|
}
 | 
						|
hcd_event;
 | 
						|
 | 
						|
/* EP event constants */
 | 
						|
#define HCD_NO_ENDPOINT			-1
 | 
						|
#define HCD_ENDPOINT_0			0
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    HCD transfer requests                                                  *
 | 
						|
 *===========================================================================*/
 | 
						|
struct hcd_datarequest {
 | 
						|
 | 
						|
	char * data;
 | 
						|
	int size;
 | 
						|
	int endpoint;
 | 
						|
	int direction;
 | 
						|
	unsigned int max_packet_size;
 | 
						|
	unsigned int interval;
 | 
						|
	hcd_speed speed;
 | 
						|
	hcd_transfer type;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct usb_ctrlrequest		hcd_ctrlrequest;
 | 
						|
typedef struct hcd_datarequest		hcd_datarequest;
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    Other definitions                                                      *
 | 
						|
 *===========================================================================*/
 | 
						|
#define HCD_MILI			1000
 | 
						|
#define HCD_MICRO			1000000
 | 
						|
#define HCD_NANO			1000000000
 | 
						|
#define HCD_NANOSLEEP_SEC(sec)		((sec)  * HCD_NANO)
 | 
						|
#define HCD_NANOSLEEP_MSEC(msec)	((msec) * HCD_MICRO)
 | 
						|
#define HCD_NANOSLEEP_USEC(usec)	((usec) * HCD_MILI)
 | 
						|
 | 
						|
/* Default USB communication parameters */
 | 
						|
#define HCD_DEFAULT_EP		0x00
 | 
						|
#define HCD_DEFAULT_ADDR	0x00
 | 
						|
 | 
						|
/* TODO: one device */
 | 
						|
#define HCD_ATTACHED_ADDR	0x01
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    Operating system specific                                              *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Generic method for registering interrupts */
 | 
						|
int hcd_os_interrupt_attach(int irq, void (*init)(void *),
 | 
						|
				void (*isr)(void *), void *priv);
 | 
						|
 | 
						|
/* Generic method for unregistering interrupts */
 | 
						|
void hcd_os_interrupt_detach(int);
 | 
						|
 | 
						|
/* Generic method for enabling interrupts */
 | 
						|
void hcd_os_interrupt_enable(int);
 | 
						|
 | 
						|
/* Generic method for disabling interrupts */
 | 
						|
void hcd_os_interrupt_disable(int);
 | 
						|
 | 
						|
/* Returns pointer to memory mapped for given arguments */
 | 
						|
void * hcd_os_regs_init(unsigned long, unsigned long);
 | 
						|
 | 
						|
/* Unregisters mapped memory */
 | 
						|
int hcd_os_regs_deinit(unsigned long, unsigned long);
 | 
						|
 | 
						|
/* Configure clocking */
 | 
						|
int hcd_os_clkconf(unsigned long, unsigned long, unsigned long);
 | 
						|
 | 
						|
/* Release clocking */
 | 
						|
int hcd_os_clkconf_release(void);
 | 
						|
 | 
						|
/* OS's sleep wrapper */
 | 
						|
void hcd_os_nanosleep(int);
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    Device handling calls                                                  *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Initializes device threading on connection */
 | 
						|
int hcd_connect_device(hcd_device_state *, hcd_thread_function);
 | 
						|
 | 
						|
/* Cleans after device disconnection */
 | 
						|
void hcd_disconnect_device(hcd_device_state *);
 | 
						|
 | 
						|
/* Locks device thread until 'hcd_device_continue' */
 | 
						|
void hcd_device_wait(hcd_device_state *, hcd_event, int);
 | 
						|
 | 
						|
/* Unlocks device thread halted by 'hcd_device_wait' */
 | 
						|
void hcd_device_continue(hcd_device_state *);
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *    Descriptor tree calls                                                  *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Creates descriptor tree based on given buffer */
 | 
						|
int hcd_buffer_to_tree(hcd_reg1 *, int, hcd_configuration *);
 | 
						|
 | 
						|
/* Frees descriptor tree */
 | 
						|
void hcd_tree_cleanup(hcd_configuration *);
 | 
						|
 | 
						|
/* Find EP in a tree */
 | 
						|
hcd_endpoint * hcd_tree_find_ep(hcd_configuration *, int);
 | 
						|
 | 
						|
 | 
						|
#endif /* !_HCD_COMMON_H_ */
 |