⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_pdc.c

📁 linux下的usb开发
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Deal with the transmit data on a USB pipe * @pdc : pdc device data structure * @pipe :  USB pipe */void tx_data(struct pdc_dev *pdc, pdc_pipe_handle_t	handle, int kick){	int txstat,tofill=1;	struct pdc_pipe *pipe = pdc->ep_pipes + handle;	struct pdc_urb	*ep_urb = pipe->urb;	int 			usb_txsize;		func_debug(("tx_data(handle=%x, kick=%x)\n", handle, kick))	if (kick == 2) {		/* BUG: sending NULL data packet after stall is not valid .....*/		/* Send NULL packet if DATA PID is not cleared by the HW 		 * This case assumed that tx_data(2) is used only for endpoint EP2 */		if((pdc_read16(CMD_READEPSTATUS+handle)) & 0x10) {			writeendpoint(handle,0,0);		}		pipe->txrx_idle = 1;		if(ep_urb) kick = 1;		else return;	}	if (!kick) {		/* Get status/clear IRQ */		txstat=pdc_read16(CMD_READEPSTATUS+handle);		/* Successfully sent some stuff: bump counts & reset buffer */		ep_urb = pipe->urb;		/* If last packet was short, and there's nothing in the buffer		   to send, then just stop here with TX disabled */		/* XXX: when the data transfer is over, go to silent mode */		if(ep_urb && (ep_urb->actual_length == ep_urb->transfer_buffer_length)) {			/* URB Complete */			pipe->urb = ep_urb->next;			ep_urb->actual_length = ep_urb->transfer_buffer_length;			ep_urb->status = PDC_URB_COMPLETE;			if(ep_urb->complete)	ep_urb->complete(ep_urb);			ep_urb = pipe->urb;		}				if(!ep_urb) {			pipe->txrx_idle = 1;			return;		}	}	ep_urb = pipe->urb;	/* Work out how many FIFOs we can fill */	tofill = 2;	txstat = pdc_read16(CMD_READEPSTATUS+handle);	if(txstat & STATUS_EPFULL0) tofill--;	if(txstat & STATUS_EPFULL1) tofill--;	/* XXX The problem with this for BOT protocol is in the IN data stage	 * after sending the data, host expects status (IN) data and we are	 * sending a NULL packet which is causing whole device to re-enumerate	 * In this case the data is multiple of MaxPacketSize 	 * So only if tx_used is there then send the data */	/* While we can send stuff... (this will fill both FIFOs) */		while( (ep_urb) && (tofill>0) && 			ep_urb->actual_length != ep_urb->transfer_buffer_length) 	{		/* Fill local packet buffer from TX buffer: if there's nothing		   to send (there might be: we need to be able to send zero		   length packets to terminate a transfer of an exact multiple		   of the buffer size), then we'll be sending a 0 byte		   packet */				usb_txsize = ep_urb->transfer_buffer_length - ep_urb->actual_length;		if ((usb_txsize)> pipe->ep_desc->max_pkt_size) usb_txsize=pipe->ep_desc->max_pkt_size;		pdc_command(CMD_WRITEEP+handle);		pdc_cwrite(usb_txsize);			while(usb_txsize>0) {			__u16	word = ((__u8*)ep_urb->transfer_buffer)[ep_urb->actual_length++];			if (usb_txsize!=1) {				usb_txsize--;				word |= (((__u8*)ep_urb->transfer_buffer)[ep_urb->actual_length++])<<8;			}			usb_txsize--;			pdc_cwrite(word);		}		/* Validate the buffer so the chip will send it */		pdc_command(CMD_VALIDATEEP+handle);		/* Not idle anymore */		pipe->txrx_idle=0;		/* Filled another buffer */		tofill--;		if(ep_urb->actual_length == ep_urb->transfer_buffer_length) {			pipe->urb = ep_urb->next;			ep_urb->actual_length = ep_urb->transfer_buffer_length;			ep_urb->status = PDC_URB_COMPLETE;			if(ep_urb->complete) ep_urb->complete(ep_urb);			ep_urb = pipe->urb;		}	}} /* End of tx_data() *//* Deal with incoming packet on the control endpoint */void rx_command(struct pdc_dev *pdc){	/* Get receiver status */    	unsigned char command[8];	int eplast;	unsigned long	bytes, rcvd_bytes;	struct pdc_pipe *pipe;	struct pdc_urb  *urb;	/* Get last transaction status (clears IRQ) */	eplast=pdc_read16(CMD_READEPSTATUS+EP0OUT);		/* Is this a setup packet? */  	if(eplast&STATUS_SETUPT) {		int i;		/* Read the packet into our buffer */		if ((i=readendpoint(EP0OUT,command,sizeof(command)))!=sizeof(command)) {			pdc_command(CMD_STALLEP+EP0IN);			pdc_command(CMD_STALLEP+EP0OUT);			detail_debug(("pdc:Short USB control read (%d bytes)!\n",i))			return;		}				/* Acknowledge out endpoints, then clear; the		   arrival of the setup packet disables the clear command		   which is issued in readendpoint() */		pdc_command(CMD_ACKSETUP);		pdc_command(CMD_CLEAREP+EP0OUT);				/* Clear all the previous data transfers on the IN endpoint */		pipe = pdc->ep_pipes + EP0OUT ;		urb = pipe->urb;		/* For each URB complete the URB */		while(urb) {			urb->status = PDC_SETUP_OVERRITE;			pipe->urb = urb->next;			if(urb->complete)	urb->complete(urb);			urb = pipe->urb;		}		/* Call the notification function of Configuration driver */		pipe = pdc->ep_pipes + EP0OUT;		if((pipe->pipe_desc) && (pipe->pipe_desc->notify))	{				pipe->pipe_desc->notify(PDC_SETUP_COMMAND,										pipe->pipe_desc->priv,										command);		}	} else {		/* If not a setup packet, it must be an OUT packet */ 		pipe = pdc->ep_pipes + EP0OUT ;		urb = pipe->urb;		if(urb) {			/* How many bytes do we need? */			bytes = urb->transfer_buffer_length - urb->actual_length;			rcvd_bytes = readendpoint(EP0OUT,&(((__u8*)urb->transfer_buffer)[urb->actual_length]),bytes);			urb->actual_length += rcvd_bytes;			/* Did we receive a short packet?? */			if(rcvd_bytes < bytes) urb->status = PDC_SHORT_PACKET;			/* Complete the urb if all the bytes are received from host or terminated			 * because of short packet			 */			if(urb->transfer_buffer_length == urb->actual_length|| urb->status == PDC_SHORT_PACKET) {				pipe->urb = urb->next;				if(urb->status == PDC_URB_PENDING) {					urb->status = PDC_URB_COMPLETE;				}				if(urb->complete) urb->complete(urb);				urb = pipe->urb;			}		} else {			/* Clear the buffer, Do we need to wait for the appl?? let us see */			readendpoint(EP0OUT,NULL,0);		}	}} /* End of rx_command *//* TX command */void tx_command(struct pdc_dev *pdc){	struct pdc_pipe		*pipe = pdc->ep_pipes + EP0IN;	int txstatus;	struct pdc_urb		*pipe_urb;	__u16				len;	func_debug(("tx_command(void)\n"))	/* Read last status & discard */	txstatus=pdc_read16(CMD_READEPSTATUS+EP0IN);	pipe_urb = pipe->urb;	if(pipe_urb) {		len = pipe_urb->transfer_buffer_length - pipe_urb->actual_length;		if(len > pipe->ep_desc->max_pkt_size)	len = pipe->ep_desc->max_pkt_size;		writeendpoint(EP0IN, &(((__u8*)pipe_urb->transfer_buffer)[pipe_urb->actual_length]), len);		pipe_urb->actual_length += len;		if(pipe_urb->actual_length == pipe_urb->transfer_buffer_length) {			pipe_urb->status = PDC_URB_COMPLETE;			pipe->urb = pipe_urb->next;			if(pipe_urb->complete) pipe_urb->complete(pipe_urb);		}	}	if(!pipe->urb) pipe->txrx_idle = 1;} /* End of tx_command *//* Interrupt Service Routine */void pdc_isr(struct isp1362_dev *dev, void *isr_data){    struct pdc_dev 			*pdc = (struct pdc_dev*)isr_data;	unsigned int 			evnt, non_ctrl_ep_event, ep_event;	struct pdc_config_dev	*bus = pdc->pdc_bus;	pdc_pipe_handle_t		handle;	struct pdc_pipe			*pipe;	while(1) {		/* Read IRQ status, masking with possible valid IRQs */		evnt= dev->int_reg&			(IE_EP0OUT|IE_EP0IN|IE_NON_CTRL_EP_MASK|IE_RST|IE_SUSP);		/* No irq? */		if (evnt==0) {			return;		}		non_ctrl_ep_event = evnt & IE_NON_CTRL_EP_MASK;		handle = EP1;		while(non_ctrl_ep_event) {			ep_event = IE_EP0OUT << handle;			if( non_ctrl_ep_event & ep_event) {				pipe = pdc->ep_pipes + handle;				if(pipe->ep_desc && pipe->pipe_desc) {					if(pipe->ep_desc->ep_dir) {						/* In pipe */						tx_data(pdc, handle, 0);	/* Data trasmission on In pipe */					} else {						/* Out pipe */						rx_data(pdc, handle);		/* Data reception on OUT pipe */					}				} else {					/* What to do?? received interrupt on an unconfigured, unopen pipe */				}				non_ctrl_ep_event &= ~ep_event;			}			handle++;		}		if (evnt&IE_EP0OUT) {			rx_command(pdc);	/* Control Out, SETUP */		}		if (evnt&IE_EP0IN) {			tx_command(pdc);	/* COntrol IN */		}		if (evnt&IE_RST) {			/*			 * Inform the configuration driver 			 * initialize the controller and connect to the bus			 */			if(bus && bus->notif)	bus->notif(bus->context, PDC_RESET);			/* notify the application */			pdc_init(dev);			pdc_connect();		}		if (evnt&IE_RESM) {			 /* Inform the configuration driver  */			if(bus && bus->notif)	bus->notif(bus->context, PDC_RESUME);		}		if (evnt&IE_SUSP) {			 /* Inform the configuration driver  */			if(bus && bus->notif)	bus->notif(bus->context, PDC_SUSPEND);			}				dev->int_reg =pdc_read32(CMD_READIRQ);	}} /* End of pdc_isr *//*------------------------------------------------------------------------* *                  External Interface functions                          * *------------------------------------------------------------------------*//* * Get the current frame number on the USB bus * @cd  class driver identifier */unsigned long   pdc_get_frame_number(struct pdc_class_drv *cd){	unsigned long flags;	unsigned long frame_number;	func_debug(("pdc_get_frame_number(cd=%p)\n",cd))	spin_lock_irqsave(&pdc_rdwr_lock, flags);	frame_number = pdc_read16(CMD_READFRAME);	frame_number &= 0x7FF;	spin_unlock_irqrestore(&pdc_rdwr_lock, flags);	return frame_number;} /* End of pdc_get_frame_number() *//*  * Set the address of the device * @context is the device context * @address is the device address on the bus */int pdc_set_device_address(unsigned long context,unsigned short address){	func_debug(("pdc_set_device_address(context=%x,address=%x\n",context, address))	pdc_write16(CMD_WRITEADDRESS, (ADDRESS_DEVEN|address));	return 0;	} /* End of pdc_set_device_address() *//* * Configure the device endpoints and Notification function */int pdc_configure_device(struct pdc_config_dev *config){	struct pdc_ep_desc	*ep_desc = config->ep_desc;	struct pdc_pipe		*pipe;    struct pdc_dev 		*pdc = usb_devices;	pdc_pipe_handle_t	handle;	__u8				index;	func_debug(("pdc_configure_device(config=%p)\n",config))	/* Initialize all pipe varaiables except the control ones */	for(handle=2; handle < PDC_MAX_PIPES; handle++) {		pipe = pdc->ep_pipes + handle;		pipe->ep_desc = NULL;		pipe->pipe_desc = NULL;		pipe->ep_state = PDC_PIPE_UNCONFIG;	}	/* Go through all the end points in the list */	for(index = 0; index < config->num_eps; index++) {		if(ep_desc->ep_num != 0 && ep_desc->ep_num < PDC_MAX_EPS) {			/* Get the pipe handle for the Endpoint */			handle = pdc_usb_to_epreg((ep_desc->ep_num),(ep_desc->ep_dir));			pipe = pdc->ep_pipes + handle;	/* Get the pipe descriptor */			pipe->ep_desc = ep_desc;			pipe->ep_state = PDC_PIPE_CONFIG;		}		ep_desc++;	}	/* Copy the configuration driver information */	pdc->pdc_bus = config;	/* Configure the endpoints in the Hardware */	pdc_configure_eps(pdc);	return 0;} /* End of pdc_configure_device() *//* * Open a data transfer pipe * @pipe_desc:	pipe information */pdc_pipe_handle_t pdc_open_pipe(struct pdc_pipe_desc *pipe_desc){	struct pdc_pipe		*pipe;	pdc_pipe_handle_t	handle = PDC_INV_PIPE_HANDLE;    struct pdc_dev 		*pdc=usb_devices;	func_debug(("pdc_open_pipe(pipe_desc=%p)\n",pipe_desc))	if(pipe_desc->ep < PDC_MAX_EPS) {		handle = pdc_usb_to_epreg((pipe_desc->ep),(pipe_desc->ep_dir));				pipe = pdc->ep_pipes + handle;			/* If pipe is configured before, then open the pipe */		if(pipe->ep_state == PDC_PIPE_CONFIG) {			/* Only configured pipes can be opened */			pipe->ep_state = PDC_PIPE_OPEN;			pipe->pipe_desc = pipe_desc;		} else {			/* else return invalid handle */			handle = PDC_INV_PIPE_HANDLE;		}		if(pipe_desc->ep == 0) {			/* 			 * This is a control end point to the user and control out pipe for us,			 * so open a control in pipe also			 */			pipe = pdc->ep_pipes + handle + 1;			pipe->ep_state = PDC_PIPE_OPEN;			pipe->pipe_desc = pipe_desc;		}	}	return handle;

⌨️ 快捷键说明

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