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

📄 sausb.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
void setAddress(int addr)
{
  DM_DbgPrintf("Set device address %x\n", addr);

  /* Note this write will not read back until the command completes! */
  IOW_REG_FIELD(struct udcarBits,&udcP->udcar,far,addr);
}

/*----------------------------------------------------------------------
 * Handle a setup message
 */
static
void doSetup()
{
  USB_DeviceRequest_T setup;
  char * descP;
  int descLength;
  int length;

  udcStats.commandCount++;

  /* Display the setup command
   */
  if (getCommand((void*)&setup) != 0) {
    DM_WarnPrintf("Failed to get command\n");
    sendDone(1);
    return;
  }

  /* Dispatch the command request.
   */
  switch(setup.bRequest) {

  case UsbSetAddress:
    DM_DbgPrintf("SETUP SET_ADDRESS %d\n", udcStats.commandCount);
    setAddress(setup.wValue.d); /* Set device address */
    sendDone(0);
    break;

  case UsbClearFeature:
    DM_DbgPrintf("SETUP CLEAR_FEATURE %d\n", udcStats.commandCount);
    if (setup.wValue.d == UsbFeatureHalt) { /* Halt */
      switch (setup.wIndex.d) {

	/* Control endpoint. Not suggested.
	 */
      case 0:
#if 0
	UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,fst,1,
		       udcP->udccs0.fst != 1,
		       fst);
#endif
	break;

	/* OUT endpoint. Set and clear FST to reset DATA0/DATA1.
	 */
      case 1:
	UDC_REG_BITSET(struct udccs1Bits,&udcP->udccs1,fst,1,
		       udcP->udccs1.fst != 1,
		       fst1);
	UDC_REG_BITSET(struct udccs1Bits,&udcP->udccs1,fst,0,
		       udcP->udccs1.fst != 0,
		       fst1);
	UDC_REG_BITSET(struct udccs1Bits,&udcP->udccs1,sst,1,
		       udcP->udccs1.sst != 0,
		       sst1);
	break;

	/* IN endpoint. Set and clear FST to reset DATA0/DATA1.
	 */
      case 2:
	UDC_REG_BITSET(struct udccs2Bits,&udcP->udccs2,fst,1,
		       udcP->udccs2.fst != 1,
		       fst2);
	UDC_REG_BITSET(struct udccs2Bits,&udcP->udccs2,fst,0,
		       udcP->udccs2.fst != 0,
		       fst2);
	UDC_REG_BITSET(struct udccs2Bits,&udcP->udccs2,sst,1,
		       udcP->udccs2.sst != 0,
		       sst2);
	break;
      }
    }
    sendDone(0);
    break;

  case UsbSetConfiguration:
    DM_DbgPrintf("SETUP SET_CONFIGURATION %d\n", udcStats.commandCount);
    sendDone(0);
    break;

  case UsbSetInterface:
    DM_DbgPrintf("SETUP SET_INTERFACE %d\n", udcStats.commandCount);
    sendDone(0);
    break;

  case UsbGetDescriptor:
    DM_DbgPrintf("SETUP GET_DESCRIPTOR %d\n", udcStats.commandCount);

    /* Find the requested descriptor
     */
    if ((descP = getDescriptor(setup.wValue.desc.type,
			       setup.wValue.desc.index,
			       &descLength)) == NULL) {
      DM_WarnPrintf("Unknown descriptor\n");
      sendDone(0);
      break;
    }

    /* Return up to the requested buffer size
     */
    length = setup.wLength;
    if (descLength < length) /* Only send back what we have room for */
      length = descLength;

    /* Start a 100ms timer to catch transmit drops
     */
    if (timerFuncP)
      timerFuncP->start(timerP, 0, reSendTimerInterval, reSendProc, NULL);

    /* Clear the OPR bit and start the data phase
     */
    sendCommandDone();

    /* Send the first 8 bytes of data. The rest will be handled in
     * subsequent interrupts.
     */
    sendData(descP, length, setup.wLength);

    break;

  case LoopCompareRx:
    {
      LoopCompareReply_T r;

      DM_DbgPrintf("SETUP LoopCompare %d\n", udcStats.commandCount);

      /* Return up to the requested buffer size
       */
      length = setup.wLength;
      if (length > sizeof(LoopCompareReply_T))
	length = sizeof(LoopCompareReply_T);

      /* Return the buffer compare counters
       */
      r.rxCompareCount = udcStats.rxCompareCount;
      r.rxCompareError = udcStats.rxCompareError;

      /* If we are in the middle of a DMA we need to reset
       */
      if (rcvDmaP) {
	DM_DbgPrintf("Check buf, w %d, b %x",
		  whichGetRcvBuf,
		  rcvBufs[whichGetRcvBuf].buf);
	if (rcvBufs[whichGetRcvBuf].buf) {
	  SA_ClearDMA(rcvDmaP,whichGetRcvBuf);
	  rcvBufs[whichGetRcvBuf].buf = NULL;
	  whichGetRcvBuf ^= 1;
	}
      }

      /* Start a 100ms timer to catch transmit drops
       */
      if (timerFuncP)
	timerFuncP->start(timerP, 0, reSendTimerInterval, reSendProc, NULL);

      /* Queue a receive
       */
      receive(thisP,rxDataP,RX_BUFSIZE,NULL);

      /* Restart the packet counter
       */
      rcvPacketCount = 0;

      /* Clear the OPR bit and start the data phase
       */
      sendCommandDone();

      /* Send the first 8 bytes of data. The rest will be handled in
       * subsequent interrupts.
       */
      sendData(&r, length, setup.wLength);
    }
    break;

  case LoopSend:
    {
      int len = setup.wValue.d;

      DM_DbgPrintf("SETUP LoopSend %d bytes - %d\n",
		   len,
		   udcStats.commandCount);

      /* Ack the command.
       */
      sendDone(0);

      /* Start a DMA transmit
       */
      if (len > TX_BUFSIZE)
	len = TX_BUFSIZE;
      transmit(thisP,txDataP,len,NULL);
    }
    break;

  default:
    DM_WarnPrintf("USBR - Unsupported SETUP %x %d\n",
	       setup.bRequest,
	       udcStats.commandCount);
    DM_WarnPrintf("%02x %02x %02x %02x %02x %02x %02x %02x",
		  setup.bmRequestType.d,
		  setup.bRequest,
		  setup.wValue.desc.index,
		  setup.wValue.desc.type,
		  setup.wIndex.d & 0xff,
		  (setup.wIndex.d >> 8) & 0xff,
		  setup.wLength & 0xff,
		  (setup.wLength >> 8) & 0xff);
    sendDone(0);
    break;
  }

  DM_DbgPrintf("Setup command done\n");
}

/*----------------------------------------------------------------------
 * Interrupt handler
 */
static
void interruptHandler(void * arg)
{
  struct udcsrBits udcsr = udcP->udcsr;

  udcStats.usbIntCount++;

  /* Handle the reset, the device will have gone back to internal defaults.
   */
  if (udcsr.rstir) { /* Reset received */

    DM_DbgPrintf("UDC port reset\n");

    /* Set the default packet size
     */
    UDC_REG_WRITE(struct packetBits,&udcP->udcomp,mps,maxPacketSize-1,
		  udcP->udcomp.mps != maxPacketSize-1,
		  comp);
    UDC_REG_WRITE(struct packetBits,&udcP->udcimp,mps,maxPacketSize-1,
		  udcP->udcimp.mps != maxPacketSize-1,
		  cimp);

    /* Clear the interrupt request bit
     */
    UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,rstir,1,
		   udcP->udcsr.rstir != 0,
		   rstir);
  }

  /* Setup command received, extract it and go execute
   */
  if (udcsr.eir) {
    struct udccs0Bits udccs0 = udcP->udccs0;

    /* Clear the interrupt request bit
     */
    UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,eir,1,
		   udcP->udcsr.eir != 0,
		   eir);

    /* If there is data to send and the transmitter is open go send
     * the next packet. But, do not continue to send if the host has
     * aborted the transfer or sent a new one. We'll clean up below.
     */
    if ((udccs0.se == 0) && (udccs0.ipr == 0) && (udccs0.opr == 0) && 
	(sendPacket))
      sendData(sendPacket, sendPacketLength, sendTotalLength);

    /* If stall ack, not sure what needs to be done here.
     */
    if (udccs0.sst) {
      DM_WarnPrintf("UDC sent STALL ack!\n");
      UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,sst,1,
		     udcP->udccs0.sst != 0,
		     sst);
    }

    /* If setup end, the host has aborted the transfer. Kill any
     * remaining packets.
     */
    if (udccs0.se) {
      //if (sendPacketLength)
	DM_WarnPrintf("Setup end set, host abort!\n");
      sendPacketLength = 0;
      sendPacket = NULL;
      UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,sse,1,
		     udcP->udccs0.se != 0,
		     sse);
    }

    /* If new command received ...
     */
    if (udccs0.opr) {
      if (sendPacket) {
	DM_WarnPrintf("New setup with old data, abort old");
	sendPacket = NULL;
      }
      DM_DbgPrintf("UDC received setup, udccs0 %x, len %d\n",
		 udccs0, udcP->udcwc.wc);
      doSetup();
    }
  }

  /* Recieve Interrupt
  */

  if (udcsr.rir || udcP->udccs1.rpc) {
/* set flag and return

 	SA_USB_RxInterruptHandler(pHWHead, pRxBuffer, *pBufflen, fRXFlag);
  } 
    int acceptPacket = 0;

    /* Count missed interrupts
     */
    if (udcsr.rir == 0)
      udcStats.missedRIR++;

    if (udcP->udccs1.rpc == 0) { /* No data to read */
      udcStats.noRPC++;
      acceptPacket = 1;
    }
    else if (udcP->udccs1.rpe) { /* Packet in error */
      char * rxBufP = rcvBufs[whichGetRcvBuf].dmaP;

      /* Pause the DMA channel so we can access the pointers
       */
      SA_PauseDMA(rcvDmaP);

      /* Back up the DMA pointer to the last packet
       */
      SA_SetDMABuffer(rcvDmaP,whichGetRcvBuf,rxBufP);

      /* Resume the DMA channel
       */
      SA_ResumeDMA(rcvDmaP);

      udcStats.badRdPacketCount++;
      acceptPacket = 1;
    }

    /* If we are polling try to read out the data. Simulate the effects
     * of the DMA mechanism.
     */
    else if (rcvDmaP == NULL) {
      int count = 0;
      char * rxBufP = rcvBufs[whichGetRcvBuf].dmaP;
      char * rxBaseP = rcvBufs[whichGetRcvBuf].buf;

      udcStats.readPacketCount++;

      while (udcP->udccs1.rne) {
	if (rxBufP < &rxBaseP[RX_BUFSIZE])
	  *rxBufP++ = udcP->udcdr.data;
	udcStats.extraFIFOReads++;
	if (++count > maxPacketSize) {
	  udcStats.fifoReadOverrun++;
	  break;
	}

	/* Update the DMA pointer
	 */
	rcvBufs[whichGetRcvBuf].dmaP = rxBufP;

	/* If we are done call the completion function
	 */
	if (rxBufP >= &rxDataP[RX_BUFSIZE])
	  rcvHandler(NULL);

      }
      acceptPacket = 1;
    }

    /* For DMA we need to clean out the part of the FIFO not
     * transfered by DMA. Get the DMA pointer and move the data
     * manually.
     */
    else if (rcvBufs[whichGetRcvBuf].buf) {
      char * p;
      int count = 0;
      int length;
      char * rxBaseP = rcvBufs[whichGetRcvBuf].buf;

      if (udcP->udccs1.rfs == 1) { /* DMA request pending, let it handle it */
	udcStats.dmaReadPending++;
	return;
      }

      udcStats.readPacketCount++;

      if (rcvBufs[whichGetRcvBuf].dmaP) {
	/* Pause the DMA channel so we can access the pointers
	 */
	SA_PauseDMA(rcvDmaP);

	/* Get the current DMA pointer and calculate how much data is still
	 * in the FIFO.
	 */
	p = (char*)SA_GetDMABuffer(rcvDmaP);
	length = p - rcvBufs[whichGetRcvBuf].dmaP;
	if (length > maxPacketSize)
	  DM_WarnPrintf("DMA read multiple %d/%d",
			length, maxPacketSize);

	/* Read out the FIFO data. We need to drain the FIFO before continue
	 * but only copy up to one packet to the output buffer.
	 */
	while (udcP->udccs1.rne) {
	  char c;
	  if (length < maxPacketSize) {
	    if (p < &rxBaseP[RX_BUFSIZE])
	      *p++ = udcP->udcdr.data;
	    udcStats.extraFIFOReads++;
	    length++;
	  }
	  else {
	    c = udcP->udcdr.data;
	    udcStats.fifoReadOverrun++;
	  }
	}

	/* If we did not recieve all the bytes complain and realign the
	 * pointer (this error should not happen with the above check unless
	 * the length was too big to start with).
	 */
	if (length != maxPacketSize) {
	  DM_WarnPrintf("Buf %d, Pkt %d len %d/%d\n",
			udcStats.rxCompareCount,
			(unsigned)(p - rxDataP) / maxPacketSize,
			length,
			maxPacketSize);
	  p += maxPacketSize - length;
	}
      
	/* Update the DMA pointer. If we've finished the transfer we
	 * have to call the completion routine manually since the DMA
	 * channel will not actually complete. This is true whether
	 * we are polling or in interrupt mode because the FIFOs are not
	 * completely drained.
	 */
	rcvBufs[whichGetRcvBuf].dmaP = p;
	if ((count=SA_SetDMABuffer(rcvDmaP,whichGetRcvBuf,p)) <= 0) {
	  if (count < 0)
	    DM_WarnPrintf("DMA channel overrun - %d\n", count);
	  rcvHandler(NULL);
	}
	else {

⌨️ 快捷键说明

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