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

📄 usb-proto.c

📁 伟大的Contiki工程, 短小精悍 的操作系统, 学习编程不可不看
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <AT91SAM7S64.h>#include <usb-api.h>#include <usb-proto.h>#include <stdio.h>#include <sys/types.h>#include <sys/process.h>#include<interrupt-utils.h>#ifndef AT91C_UDP_STALLSENT#define AT91C_UDP_STALLSENT AT91C_UDP_ISOERROR#endif/* Bits that won't effect the state if they're written at a specific level. *//* Bits that should be written as 1 */#define NO_EFFECT_BITS (AT91C_UDP_TXCOMP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP \			| AT91C_UDP_ISOERROR | AT91C_UDP_RX_DATA_BK1)/* Also includes bits that should be written as 0 */#define NO_EFFECT_MASK (NO_EFFECT_BITS | AT91C_UDP_TXPKTRDY)#define RXBYTECNT(s) (((s)>>16)&0x7ff)/* Index in endpoint array */#define EP_INDEX(addr) (((addr) & 0x7f) - 1)/* Number of hardware endpoint */#define EP_HW_NUM(addr) ((addr) & 0x7f)static inline voidudp_set_ep_ctrl_flags(AT91_REG *reg, unsigned int flags,		      unsigned int write_mask, unsigned int check_mask){  while ( (*reg & check_mask) != (flags & check_mask)) {    *reg = (*reg & ~write_mask) | flags;   }}#define UDP_SET_EP_CTRL_FLAGS(reg, flags, mask) \udp_set_ep_ctrl_flags((reg), \  (NO_EFFECT_BITS & ~(mask)) | ((flags) & (mask)), (mask) | NO_EFFECT_MASK,\  (mask))voidusb_error_stall(){  /* Disable all USB events */  *AT91C_AIC_IDCR = (1 << AT91C_ID_UDP);  /* Set stall state */  UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],			AT91C_UDP_FORCESTALL, AT91C_UDP_FORCESTALL);  /* Reenable interrupt */  *AT91C_AIC_IECR = (1 << AT91C_ID_UDP);  puts("Stalled");}volatile unsigned char usb_events = 0;struct process *usb_handler_process = NULL;#define NUM_EP 4volatile unsigned char usb_endpoint_events[NUM_EP] = {0,0,0,0};static volatile USBEndpoint usb_endpoints[NUM_EP - 1];volatile unsigned char usb_flags = 0;#define USB_FLAG_ADDRESS_PENDING 0x01#define USB_FLAG_RECEIVING_CTRL 0x04#define USB_FLAG_SEND_ZLP 0x08 /* If the last packet has max length,				  then it needs to be followed by a				  zero length packet to mark the				  end. */static unsigned short usb_ctrl_send_len = 0;static const unsigned char *usb_ctrl_send_pos = NULL;unsigned char usb_ctrl_data_buffer[MAX_CTRL_DATA];unsigned short usb_ctrl_data_len = 0;static voidwrite_endpoint(unsigned int hw_ep,	       const unsigned char *buffer, unsigned short len){  AT91_REG *fdr = &AT91C_UDP_FDR[hw_ep];  {#if 0    unsigned int i;    printf("Sending: ");    for (i = 0; i< len; i++) printf(" %02x", buffer[i]);    putchar('\n');#endif  }   while(len > 0) {    *fdr = *buffer++;    len--;  }  /* Start transmission */  UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[hw_ep],			AT91C_UDP_TXPKTRDY, AT91C_UDP_TXPKTRDY); }     static voidwrite_ctrl(){  if (usb_ctrl_send_pos) {    unsigned int xfer_len = usb_ctrl_send_len;    /* Check if FIFO is ready */    if (AT91C_UDP_CSR[0] & AT91C_UDP_TXPKTRDY) return;    if (xfer_len > CTRL_EP_SIZE) xfer_len = CTRL_EP_SIZE;    write_endpoint(0, usb_ctrl_send_pos, xfer_len);    if (xfer_len < CTRL_EP_SIZE) {      /* Last packet, stop sending */      usb_ctrl_send_pos = NULL;    } else {      usb_ctrl_send_pos += xfer_len;      usb_ctrl_send_len -= xfer_len;      if (usb_ctrl_send_len == 0 && !(usb_flags & USB_FLAG_SEND_ZLP)) {	usb_ctrl_send_pos = NULL;      }    }  }}static unsigned charread_buffered_endpoint(volatile USBEndpoint *ep){  unsigned char len;  unsigned char mask = ep->buf_size_mask;  unsigned char *buffer = ep->buffer;  unsigned char pos = (ep->buf_pos + ep->buf_len) & mask;  AT91_REG *fdr = &AT91C_UDP_FDR[EP_HW_NUM(ep->addr)];   len = RXBYTECNT(AT91C_UDP_CSR[EP_HW_NUM(ep->addr)]);  if (mask + 1 - ep->buf_len < len) return 0;  ep->buf_len += len;  while(len-- > 0) {    buffer[pos] = *fdr;    pos = (pos + 1) & mask;  }  return 1;}unsigned intusb_recv_data(unsigned char ep_addr, unsigned char *dat, unsigned int len){  volatile USBEndpoint *ep = &usb_endpoints[EP_INDEX(ep_addr)];  unsigned char mask = ep->buf_size_mask;  *AT91C_UDP_IDR = 1<<EP_HW_NUM(ep_addr);  {    unsigned char l;    unsigned char *to = ep->buffer;    unsigned char pos = ep->buf_pos;    if (ep->buf_len < len) len = ep->buf_len;    ep->buf_len -= len;    l = len;    while(l-- > 0) {      *dat++ = to[pos];       pos = (pos + 1) & mask;    }    ep->buf_pos = pos;  }  ep->flags &= ~USB_EP_FLAGS_RECV_BLOCKED;  *AT91C_UDP_IER = 1<<EP_HW_NUM(ep_addr);  return len;}voidwrite_buffered_endpoint(volatile USBEndpoint *ep){  unsigned int irq = disableIRQ();  {    unsigned int pos = ep->buf_pos;    unsigned int xfer_len = ep->buf_len;    unsigned int mask = ep->buf_size_mask;    const unsigned char *buf_tmp = ep->buffer;    AT91_REG *fdr = &AT91C_UDP_FDR[EP_HW_NUM(ep->addr)];     if (!(ep->flags & USB_EP_FLAGS_TRANSMITTING)	&& !(AT91C_UDP_CSR[EP_HW_NUM(ep->addr)] & AT91C_UDP_TXPKTRDY)) {      if (xfer_len > NON_CTRL_XFER_SIZE)  xfer_len = NON_CTRL_XFER_SIZE;      ep->buf_len -= xfer_len;      /* printf("Writing %d to 0x%02x\n", xfer_len, ep->addr); */      while(xfer_len > 0) {	*fdr = buf_tmp[pos];	pos = (pos + 1) & mask;	xfer_len--;      }      ep->flags |= USB_EP_FLAGS_TRANSMITTING;      /* Start transmission */      UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[EP_HW_NUM(ep->addr)],			    AT91C_UDP_TXPKTRDY, AT91C_UDP_TXPKTRDY);      ep->buf_pos = pos;    }  }  restoreIRQ(irq);}static voidwrite_send_buffer(unsigned char *buffer, const unsigned char *dat,		  unsigned int len){  while(len-- > 0) {    *buffer++ = *dat++;  }}voidusb_send_buffer_get(unsigned char ep_addr, unsigned int offset,		    unsigned char **dat, unsigned int *lenp){  unsigned int pos;  volatile USBEndpoint *ep = &usb_endpoints[EP_INDEX(ep_addr)];  unsigned int size = ep->buf_size_mask + 1;  unsigned int len;  *AT91C_UDP_IDR = 1<<EP_HW_NUM(ep_addr);  len = size - ep->buf_len;  pos = (ep->buf_pos + offset + ep->buf_len) & (size - 1);  *AT91C_UDP_IER = 1<<EP_HW_NUM(ep_addr);  if (offset >= len) {    len = 0;  } else {    len -= offset;  }  if (pos + len > size) len = size - pos;  *dat = &ep->buffer[pos];  *lenp = len;}       voidusb_send_buffer_commit(unsigned char ep_addr, unsigned int len){  volatile USBEndpoint *ep = &usb_endpoints[EP_INDEX(ep_addr)];  *AT91C_UDP_IDR = 1<<EP_HW_NUM(ep_addr);  ep->buf_len += len;  write_buffered_endpoint(ep);  *AT91C_UDP_IER = 1<<EP_HW_NUM(ep_addr);}unsigned intusb_send_data(unsigned char ep_addr, const unsigned char *dat, unsigned int len){  unsigned char *write_pos;  unsigned int write_len;  unsigned int full_len = len;  /* printf("usb_send_data %02x: IMR=%08x\n",ep_addr, *AT91C_UDP_IMR); */  while(len > 0) {    usb_send_buffer_get(ep_addr, 0, &write_pos, &write_len);    if (write_len == 0) break;    if (write_len > len) write_len = len;    write_send_buffer(write_pos, dat, write_len);    /* printf("Pos: %p, len %d\n", write_pos, write_len); */    usb_send_buffer_commit(ep_addr, write_len);    dat += write_len;    len -= write_len;  }  return full_len - len;}voidusb_send_ctrl_response(const unsigned char *buffer, unsigned short len){  if (AT91C_UDP_CSR[0] & AT91C_UDP_TXPKTRDY) return;  *AT91C_UDP_IDR = AT91C_UDP_EP0;  if (len >= usb_setup_buffer.wLength) {    len = usb_setup_buffer.wLength;	/* Truncate if too long */    usb_flags &= ~USB_FLAG_SEND_ZLP;  } else {    /* Send ZLP if the response is shorter than requested */    usb_flags |= USB_FLAG_SEND_ZLP;  }  usb_ctrl_send_pos = buffer;  usb_ctrl_send_len = len;  write_ctrl();  *AT91C_UDP_IER = AT91C_UDP_EP0;}void usb_send_ctrl_status(){  *AT91C_UDP_IDR = AT91C_UDP_EP0;  /* Start transmission */  UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],			AT91C_UDP_TXPKTRDY, AT91C_UDP_TXPKTRDY);  *AT91C_UDP_IER = AT91C_UDP_EP0;}static voidnotify_process(unsigned char events){  usb_events |= events;  if (usb_handler_process) {    process_poll(usb_handler_process);  }}voidusb_reset(){  /* Setup endpoint 0 */  UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],			AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS,			AT91C_UDP_EPTYPE | AT91C_UDP_EPEDS);

⌨️ 快捷键说明

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