📄 usb_pdc.c
字号:
* 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 + -