diff options
Diffstat (limited to 'include/usb.h')
| -rw-r--r-- | include/usb.h | 352 | 
1 files changed, 352 insertions, 0 deletions
| diff --git a/include/usb.h b/include/usb.h new file mode 100644 index 000000000..c3cc8903a --- /dev/null +++ b/include/usb.h @@ -0,0 +1,352 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_H_ +#define _USB_H_ + +#include <usb_defs.h> + +/* Everything is aribtrary */ +#define USB_ALTSETTINGALLOC          4 +#define USB_MAXALTSETTING	           128  /* Hard limit */ + +#define USB_MAX_DEVICE              32 +#define USB_MAXCONFIG		            8 +#define USB_MAXINTERFACES	          8 +#define USB_MAXENDPOINTS	          16 +#define USB_MAXCHILDREN  						8 	/* This is arbitrary */ +#define USB_MAX_HUB									16 + +#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ + + +/* String descriptor */ +struct usb_string_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned short wData[1]; +} __attribute__ ((packed)); + +/* device request (setup) */ +struct devrequest { +	unsigned char requesttype; +	unsigned char request; +	unsigned short value; +	unsigned short index; +	unsigned short length; +} __attribute__ ((packed)); + + + +/* All standard descriptors have these 2 fields in common */ +struct usb_descriptor_header { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +} __attribute__ ((packed)); + +/* Device descriptor */ +struct usb_device_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned short bcdUSB; +	unsigned char  bDeviceClass; +	unsigned char  bDeviceSubClass; +	unsigned char  bDeviceProtocol; +	unsigned char  bMaxPacketSize0; +	unsigned short idVendor; +	unsigned short idProduct; +	unsigned short bcdDevice; +	unsigned char  iManufacturer; +	unsigned char  iProduct; +	unsigned char  iSerialNumber; +	unsigned char  bNumConfigurations; +} __attribute__ ((packed)); + + +/* Endpoint descriptor */ +struct usb_endpoint_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned char  bEndpointAddress; +	unsigned char  bmAttributes; +	unsigned short wMaxPacketSize; +	unsigned char  bInterval; +	unsigned char  bRefresh; +	unsigned char  bSynchAddress; + +} __attribute__ ((packed)); +/* Interface descriptor */ +struct usb_interface_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned char  bInterfaceNumber; +	unsigned char  bAlternateSetting; +	unsigned char  bNumEndpoints; +	unsigned char  bInterfaceClass; +	unsigned char  bInterfaceSubClass; +	unsigned char  bInterfaceProtocol; +	unsigned char  iInterface; + +	unsigned char  no_of_ep; +	unsigned char  act_altsetting; +	struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; +} __attribute__ ((packed)); + + +/* Configuration descriptor information.. */ +struct usb_config_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned short wTotalLength; +	unsigned char  bNumInterfaces; +	unsigned char  bConfigurationValue; +	unsigned char  iConfiguration; +	unsigned char  bmAttributes; +	unsigned char  MaxPower; + +	unsigned char  no_of_if;			/* number of interfaces */ +	struct usb_interface_descriptor if_desc[USB_MAXINTERFACES]; +} __attribute__ ((packed)); + + +struct usb_device { +	int devnum;								/* Device number on USB bus */ +	int slow;									/* Slow device? */ +	char mf[32];		     			/* manufacturer */ +	char prod[32];		     		/* product */ +	char serial[32];       	  /* serial number */ + +	int maxpacketsize;		    /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ +	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */ +	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */ +                            /* [0] = IN, [1] = OUT */ +	int epmaxpacketin[16];		/* INput endpoint specific maximums */ +	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */ + +	int configno;			/* selected config number */ +	struct usb_device_descriptor descriptor; /* Device Descriptor */ +	struct usb_config_descriptor config; /* config descriptor */ + +	int have_langid;		/* whether string_langid is valid yet */ +	int string_langid;		/* language ID for strings */ +	int (*irq_handle)(struct usb_device *dev); +	unsigned long irq_status; +	int irq_act_len;			/* transfered bytes */ +	void *privptr; +	/* +	 * Child devices -  if this is a hub device +	 * Each instance needs its own set of data structures. +	 */ +	unsigned long status; +	int act_len;			/* transfered bytes */ +	int maxchild;			/* Number of ports if hub */ +	struct usb_device *parent; +	struct usb_device *children[USB_MAXCHILDREN]; +}; + +/********************************************************************** + * this is how the lowlevel part communicate with the outer world + */ + +#ifdef CONFIG_USB_UHCI +int usb_lowlevel_init(void); +int usb_lowlevel_stop(void); +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len); +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +			int transfer_len,struct devrequest *setup); +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +			int transfer_len, int interval); + +/* Defines */ +#define USB_UHCI_VEND_ID 0x8086 +#define USB_UHCI_DEV_ID  0x7112 + +#else +#error USB Lowlevel not defined +#endif + +#ifdef CONFIG_USB_STORAGE + +#define USB_MAX_STOR_DEV 5 +block_dev_desc_t *usb_stor_get_dev(int index); +int usb_stor_scan(int mode); + +#endif + +#ifdef CONFIG_USB_KEYBOARD + +int drv_usb_kbd_init(void); +int usb_kbd_deregister(void); + +#endif +/* routines */ +int usb_init(void); /* initialize the USB Controller */ +int usb_stop(void); /* stop the USB Controller */ + + +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); +struct usb_device * usb_get_dev_index(int index); +int usb_control_msg(struct usb_device *dev, unsigned int pipe, +			unsigned char request, unsigned char requesttype, +			unsigned short value, unsigned short index, +			void *data, unsigned short size, int timeout); +int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, +			void *data, int len, int *actual_length, int timeout); +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, +			void *buffer,int transfer_len, int interval); +void usb_disable_asynch(int disable); +int usb_maxpacket(struct usb_device *dev,unsigned long pipe); +void __inline__ wait_ms(unsigned long ms); +int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno); +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size); +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, +		unsigned char type, unsigned char id, void *buf, int size); +int usb_clear_halt(struct usb_device *dev, int pipe); +int usb_string(struct usb_device *dev, int index, char *buf, size_t size); +int usb_set_interface(struct usb_device *dev, int interface, int alternate); + +/* big endian -> little endian conversion */ +#define swap_16(x) \ +	((unsigned short)( \ +		(((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ +		(((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) +#define swap_32(x) \ +	((unsigned long)( \ +		(((unsigned long)(x) & (unsigned long)0x000000ffUL) << 24) | \ +		(((unsigned long)(x) & (unsigned long)0x0000ff00UL) <<  8) | \ +		(((unsigned long)(x) & (unsigned long)0x00ff0000UL) >>  8) | \ +		(((unsigned long)(x) & (unsigned long)0xff000000UL) >> 24) )) + +/* + * Calling this entity a "pipe" is glorifying it. A USB pipe + * is something embarrassingly simple: it basically consists + * of the following information: + *  - device number (7 bits) + *  - endpoint number (4 bits) + *  - current Data0/1 state (1 bit) + *  - direction (1 bit) + *  - speed (1 bit) + *  - max packet size (2 bits: 8, 16, 32 or 64) + *  - pipe type (2 bits: control, interrupt, bulk, isochronous) + * + * That's 18 bits. Really. Nothing more. And the USB people have + * documented these eighteen bits as some kind of glorious + * virtual data structure. + * + * Let's not fall in that trap. We'll just encode it as a simple + * unsigned int. The encoding is: + * + *  - max size:		bits 0-1	(00 = 8, 01 = 16, 10 = 32, 11 = 64) + *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In]) + *  - device:		bits 8-14 + *  - endpoint:		bits 15-18 + *  - Data0/1:		bit 19 + *  - speed:		bit 26		(0 = Full, 1 = Low Speed) + *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk) + * + * Why? Because it's arbitrary, and whatever encoding we select is really + * up to us. This one happens to share a lot of bit positions with the UHCI + * specification, so that much of the uhci driver can just mask the bits + * appropriately. + */ +/* Create various pipes... */ +#define create_pipe(dev,endpoint) \ +		(((dev)->devnum << 8) | (endpoint << 15) | ((dev)->slow << 26) | (dev)->maxpacketsize) +#define default_pipe(dev) ((dev)->slow <<26) + +#define usb_sndctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | create_pipe(dev,endpoint)) +#define usb_rcvctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint)) +#define usb_rcvisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | create_pipe(dev,endpoint)) +#define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint)) +#define usb_rcvintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30) | default_pipe(dev)) +#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | default_pipe(dev) | USB_DIR_IN) + +/* The D0/D1 toggle bits */ +#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) +#define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << ep)) +#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep)) + +/* Endpoint halt control/status */ +#define usb_endpoint_out(ep_dir)	(((ep_dir >> 7) & 1) ^ 1) +#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) +#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) +#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) + +#define usb_packetid(pipe)	(((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT) + +#define usb_pipeout(pipe)	((((pipe) >> 7) & 1) ^ 1) +#define usb_pipein(pipe)	(((pipe) >> 7) & 1) +#define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f) +#define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff) +#define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf) +#define usb_pipedata(pipe)	(((pipe) >> 19) & 1) +#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1) +#define usb_pipetype(pipe)	(((pipe) >> 30) & 3) +#define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) +#define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT) +#define usb_pipecontrol(pipe)	(usb_pipetype((pipe)) == PIPE_CONTROL) +#define usb_pipebulk(pipe)	(usb_pipetype((pipe)) == PIPE_BULK) + + +/************************************************************************* + * Hub Stuff + */ +struct usb_port_status { +	unsigned short wPortStatus; +	unsigned short wPortChange; +} __attribute__ ((packed)); + +struct usb_hub_status { +	unsigned short wHubStatus; +	unsigned short wHubChange; +} __attribute__ ((packed)); + + +/* Hub descriptor */ +struct usb_hub_descriptor { +	unsigned char  bLength; +	unsigned char  bDescriptorType; +	unsigned char  bNbrPorts; +	unsigned short wHubCharacteristics; +	unsigned char  bPwrOn2PwrGood; +	unsigned char  bHubContrCurrent; +	unsigned char  DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; +	unsigned char  PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; +		/* DeviceRemovable and PortPwrCtrlMask want to be variable-length +	   bitmaps that hold max 255 entries. (bit0 is ignored) */ +} __attribute__ ((packed)); + + +struct usb_hub_device { +	struct usb_device *pusb_dev; +	struct usb_hub_descriptor desc; +}; + +#endif /*_USB_H_ */ |