usb.h

来自「AMLOGIC DPF source code」· C头文件 代码 · 共 1,017 行 · 第 1/3 页

H
1,017
字号
 * transfers are at least double buffered, and then explicitly resubmitted
 * in completion handlers, so
 * that data (such as audio or video) streams at as constant a rate as the
 * host controller scheduler can support.
 *
 * Completion Callbacks:
 *
 * The completion callback is made in_interrupt(), and one of the first
 * things that a completion handler should do is check the status field.
 * The status field is provided for all URBs.  It is used to report
 * unlinked URBs, and status for all non-ISO transfers.  It should not
 * be examined before the URB is returned to the completion handler.
 *
 * The context field is normally used to link URBs back to the relevant
 * driver or request state.
 *
 * When the completion callback is invoked for non-isochronous URBs, the
 * actual_length field tells how many bytes were transferred.  This field
 * is updated even when the URB terminated with an error or was unlinked.
 *
 * ISO transfer status is reported in the status and actual_length fields
 * of the iso_frame_desc array, and the number of errors is reported in
 * error_count.  Completion callbacks for ISO transfers will normally
 * (re)submit URBs to ensure a constant transfer rate.
 *
 * Note that even fields marked "public" should not be touched by the driver
 * when the urb is owned by the hcd, that is, since the call to
 * usb_submit_urb() till the entry into the completion routine.
 */
typedef struct urb
{
	void *hcpriv;			/* private data for host controller */
	int bandwidth;			/* bandwidth for INT/ISO request */
	unsigned use_count;		/* concurrent submissions counter */
	__u8 reject;			/* submissions will fail */

      __u8 state;						// 2 - SETUP, 1 - DATA, 0 - ACK
//	__u8 data_path ;	//0-SDRAM, 1- PARSER  //for typhoon

	/* public, documented fields in the urb that can be used by drivers */
	struct list_head urb_list;	/* list head for use by the urb owner */
	struct usb_device *dev; 	/* (in) pointer to associated device */
	unsigned int pipe;		/* (in) pipe information */
	int status;			/* (return) non-ISO status */
	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/
	void *transfer_buffer;		/* (in) associated data buffer */
	dma_addr_t transfer_dma;	/* (in) dma addr for transfer_buffer */	
	int transfer_buffer_length;	/* (in) data buffer length */
	int actual_length;		/* (return) actual transfer length */
	unsigned char *setup_packet;	/* (in) setup packet (control only) */
	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */	
	int start_frame;		/* (modify) start frame (ISO) */
	int number_of_packets;		/* (in) number of ISO packets */
	int interval;			/* (modify) transfer interval (INT/ISO) */
	int error_count;		/* (return) number of ISO errors */
	void *context;			/* (in) context for completion */
	OS_EVENT *done; 	/*internal  use only 	*/
	usb_complete_t complete;	/* (in) completion routine */
	struct usb_iso_packet_descriptor iso_frame_desc[0];	/* (in) ISO ONLY */
} urb_t;
//USB data_path
#define USB_DP_PARSER	1
#define USB_DP_SDRAM	0


/* -------------------------------------------------------------------------- */

/**
 * usb_fill_control_urb - initializes a control urb
 * @urb: pointer to the urb to initialize.
 * @dev: pointer to the struct usb_device for this urb.
 * @pipe: the endpoint pipe
 * @setup_packet: pointer to the setup_packet buffer
 * @transfer_buffer: pointer to the transfer buffer
 * @buffer_length: length of the transfer buffer
 * @complete: pointer to the usb_complete_t function
 * @context: what to set the urb context to.
 *
 * Initializes a control urb with the proper information needed to submit
 * it to a device.
 */
static inline void usb_fill_control_urb (struct urb *urb,
					 struct usb_device *dev,
					 unsigned int pipe,
					 unsigned char *setup_packet,
					 void *transfer_buffer,
					 int buffer_length,
					 usb_complete_t complete,
					 void *context)
{
	urb->dev = dev;
	urb->pipe = pipe;
	urb->setup_packet = setup_packet;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length;
	urb->complete = complete;
	urb->context = context;
}

/**
 * usb_fill_bulk_urb - macro to help initialize a bulk urb
 * @urb: pointer to the urb to initialize.
 * @dev: pointer to the struct usb_device for this urb.
 * @pipe: the endpoint pipe
 * @transfer_buffer: pointer to the transfer buffer
 * @buffer_length: length of the transfer buffer
 * @complete: pointer to the usb_complete_t function
 * @context: what to set the urb context to.
 *
 * Initializes a bulk urb with the proper information needed to submit it
 * to a device.
 */
static inline void usb_fill_bulk_urb (struct urb *urb,
				      struct usb_device *dev,
				      unsigned int pipe,
				      void *transfer_buffer,
				      int buffer_length,
				      usb_complete_t complete,
				      void *context)
{
	urb->dev = dev;
	urb->pipe = pipe;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length;
	urb->complete = complete;
	urb->context = context;
}

/**
 * usb_fill_int_urb - macro to help initialize a interrupt urb
 * @urb: pointer to the urb to initialize.
 * @dev: pointer to the struct usb_device for this urb.
 * @pipe: the endpoint pipe
 * @transfer_buffer: pointer to the transfer buffer
 * @buffer_length: length of the transfer buffer
 * @complete: pointer to the usb_complete_t function
 * @context: what to set the urb context to.
 * @interval: what to set the urb interval to, encoded like
 *	the endpoint descriptor's bInterval value.
 *
 * Initializes a interrupt urb with the proper information needed to submit
 * it to a device.
 * Note that high speed interrupt endpoints use a logarithmic encoding of
 * the endpoint interval, and express polling intervals in microframes
 * (eight per millisecond) rather than in frames (one per millisecond).
 */
static inline void usb_fill_int_urb (struct urb *urb,
				     struct usb_device *dev,
				     unsigned int pipe,
				     void *transfer_buffer,
				     int buffer_length,
				     usb_complete_t complete,
				     void *context,
				     int interval)
{
	urb->dev = dev;
	urb->pipe = pipe;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length;
	urb->complete = complete;
	urb->context = context;
	if (dev->speed == USB_SPEED_HIGH)
		urb->interval = 1 << (interval - 1);
	else
		urb->interval = interval;
	urb->start_frame = -1;
}


struct urb *usb_alloc_urb(int iso_packets);
struct urb *usb_alloc_urb_no_sem(int iso_packets);

extern void usb_free_urb(struct urb *urb);
#define usb_put_urb usb_free_urb
int usb_submit_urb(urb_t *urb);
extern int usb_unlink_urb(struct urb *urb);
extern void usb_kill_urb(struct urb *urb);
    

/*-------------------------------------------------------------------*
 *                         SYNCHRONOUS CALL SUPPORT                  *
 *-------------------------------------------------------------------*/

extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
	__u8 request, __u8 requesttype, __u16 value, __u16 index,
	void *data, __u16 size, int timeout);
extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
	void *data, int len, int *actual_length,
	int timeout);

/* wrappers around usb_control_msg() for the most common standard requests */
extern int usb_get_device_descriptor(struct usb_device *dev,
		unsigned int size);
extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
	unsigned char descindex, void *buf, int size);
extern int usb_get_status(struct usb_device *dev,
	int type, int target, void *data);
extern int usb_get_string(struct usb_device *dev,
	unsigned short langid, unsigned char index, void *buf, int size);
extern int usb_string(struct usb_device *dev, int index,
	char *buf, size_t size);

/* wrappers that also update important state inside usbcore */
extern int usb_clear_halt(struct usb_device *dev, int pipe);
extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
extern int usb_unbind_interface(struct usb_interface *intf);
extern int usb_probe_interface(struct usb_interface *intf);
extern void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf);
extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr);
/*
 * timeouts, in milliseconds, used for sending/receiving control messages
 * they typically complete within a few frames (msec) after they're issued
 * USB identifies 5 second timeouts, maybe more in a few cases, and a few
 * slow devices (like some MGE Ellipse UPSes) actually push that limit.
 */
#define USB_CTRL_GET_TIMEOUT	5000
#define USB_CTRL_SET_TIMEOUT	5000

/* -------------------------------------------------------------------------- */

/*
 * For various legacy reasons, Linux has a small cookie that's paired with
 * a struct usb_device to identify an endpoint queue.  Queue characteristics
 * are defined by the endpoint's descriptor.  This cookie is called a "pipe",
 * an unsigned int encoded as:
 *
 *  - direction:	bit 7		(0 = Host-to-Device [Out],
 *					 1 = Device-to-Host [In] ...
 *					like endpoint bEndpointAddress)
 *  - device address:	bits 8-14       ... bit positions known to uhci-hcd
 *  - endpoint:		bits 15-18      ... bit positions known to uhci-hcd
 *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt,
 *					 10 = control, 11 = bulk)
 *
 * Given the device address and endpoint descriptor, pipes are redundant.
 */

/* NOTE:  these are not the standard USB_ENDPOINT_XFER_* values!! */
/* (yet ... they're the values used by usbfs) */
#define PIPE_ISOCHRONOUS		0
#define PIPE_INTERRUPT			1
#define PIPE_CONTROL			2
#define PIPE_BULK			3

#define usb_pipein(pipe)	((pipe) & USB_DIR_IN)
#define usb_pipeout(pipe)	(!usb_pipein(pipe))

#define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)
#define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)

#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)

/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#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)))

#define usb_packetid(pipe)      (((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)

#define usb_pipe_endpdev(pipe)  (((pipe) >> 8) & 0x7ff)
#define usb_pipedata(pipe)      (((pipe) >> 19) & 1)
#define usb_pipeslow(pipe)      (((pipe) >> 26) & 1)


/* 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 __create_pipe(dev, endpoint)	((dev->devnum << 8) | ((endpoint) << 15) | \
										 ((dev->speed == USB_SPEED_LOW) << 26))
#define __default_pipe(dev)				((dev->speed == USB_SPEED_LOW) << 26)

/* Create various pipes... */
#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)

unsigned short usb_maxpacket(struct usb_device *udev, int pipe, int is_out);

/*-------------------------------------------------------------------------*/

/* USB status codes */

#define USB_CC_MASK				0x0f
#define USB_ST_NOERROR			0x00
#define USB_ST_CRC				0x01
#define USB_ST_BITSTUFF			0x02
#define USB_ST_TGLMISMATCH		0x03
#define USB_ST_STALL			0x04 /* pipe stalled, also in urb->status*/
#define USB_ST_NORESPONSE		0x05 /* device not responding/handshaking */
#define USB_ST_DATAOVERRUN		0x08
#define USB_ST_DATAUNDERRUN		0x09
#define USB_ST_URB_INVALID  	0x0a /* invalid value/transfer type */
#define USB_ST_URB_REQ_ERROR  	0x0b /* invalid endpoint */
#define USB_ST_BUFFEROVERRUN	0x0c
#define USB_ST_BUFFERUNDERRUN	0x0d

#define USB_ST_EPHALTED			0x10
#define USB_ST_TIMEOUT			0x20 /* communication timed out, also in urb->status**/
#define USB_ST_REMOVED			0x40 /* device not existing or removed */
#define USB_ST_NOTSUPPORTED		0x80


/* api provided by usbd */
struct usb_device *usb_alloc_dev(struct usb_device *parent,
					struct usb_bus *bus, unsigned port0);
void usb_release_dev(struct usb_device *udev);
#define usb_free_dev usb_release_dev
//void usb_free_dev(usb_device_t *dev);
int  usb_connect(usb_device_t *dev);
void usb_disconnect(usb_device_t **dev);
void usb_find_driver(usb_device_t *dev);
void usb_release_driver(usb_device_t *dev);
//int usb_device_reset(usb_device_t *dev);
//int usb_clear_halt(usb_device_t *dev, __u32 pipe);
__u16 usb_get_frame_number(struct usb_device *dev);
void usb_set_device_state(struct usb_device *udev,
		enum usb_device_state new_state);

void usb_init();
void usb_exit();

#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?