/* This low-level send bytes function is NON-BLOCKING; blocking behavior, with * a timeout, is implemented in usercode (or in the Wirish C++ high level * implementation). * * This function will quickly copy up to 64 bytes of data (out of an * arbitrarily large buffer) into the USB peripheral TX buffer and return the * number placed in that buffer. It is up to usercode to divide larger packets * into 64-byte chunks to guarantee delivery. Use usbGetCountTx() to determine * whether the bytes were ACTUALLY recieved by the host or just transfered to * the buffer. * * The function will return -1 if it doesn't think that the USB host is * "connected", but it can't detect this state robustly. "Connected" in this * context means that an actual program on the Host operating system is * connected to the virtual COM/ttyACM device and is recieving the bytes; the * Host operating system is almost always configured and keeping this endpoint * alive, but the bytes never get read out of the endpoint buffer. * * The behavior of this function is subtle and frustrating; it has gone through * many simpler and cleaner implementation that frustratingly don't work cross * platform. * * */ uint16 usbSendBytes(uint8* sendBuf, uint16 len) { uint16 loaded = 0; if (bDeviceState != CONFIGURED || (!usbGetDTR() && !usbGetRTS())) { // Indicates to caller to stop trying, were not configured/connected // The DTR and RTS lines are handled differently on major platforms, so // the above logic is unreliable return 0; } // Due to a variety of shit this is how we roll; all buffering etc is pushed // upstream if (countTx) { return 0; } // We can only put VCOM_TX_EPSIZE bytes in the buffer if(len > VCOM_TX_EPSIZE) { loaded = VCOM_TX_EPSIZE; } else { loaded = len; } // Try to load some bytes if we can if (loaded) { UserToPMABufferCopy(sendBuf,VCOM_TX_ADDR + countTx, loaded); _SetEPTxCount(VCOM_TX_ENDP, countTx+loaded); _SetEPTxValid(VCOM_TX_ENDP); countTx += loaded; } return loaded; }
/* This low-level send bytes function is NON-BLOCKING; blocking behavior, with * a timeout, is implemented in usercode (or in the Wirish C++ high level * implementation). * * This function will quickly copy up to 64 bytes of data (out of an * arbitrarily large buffer) into the USB peripheral TX buffer and return the * number placed in that buffer. It is up to usercode to divide larger packets * into 64-byte chunks to guarantee delivery. * * */ void usbBlockingSendByte(char ch) { while (countTx); UserToPMABufferCopy((uint8*)&ch,VCOM_TX_ADDR,1); _SetEPTxCount(VCOM_TX_ENDP,1); _SetEPTxValid(VCOM_TX_ENDP); countTx = 1; while (countTx); }
void ep_send(int ep_nr, const u8 * buf, int len) { int i; u32 * ptr = (u32*)(((u16)*EPREG_TXBUF_ADDR(ep_nr)) * 2 + PMA_ADDR); //TRACE("send ep<%d>: ptr %p, len %d\n", ep_nr, ptr, len); //DUMPHEX((u8*)buf, len); for (i=0; i<len; i+=2) { (*ptr++) = ((rt_uint16_t)buf[i+1] << 8) | buf[i]; } if (len & 0x1) (*ptr++) = buf[i]; _SetEPTxCount(ep_nr, len); _SetEPTxStatus(ep_nr, EP_TX_VALID); }
uint32 usbSendBytes(const uint8* sendBuf, uint32 len) { /* Last transmission hasn't finished, abort */ if (countTx) { return 0; } // We can only put VCOM_TX_EPSIZE bytes in the buffer if (len > VCOM_TX_EPSIZE / 2) { len = VCOM_TX_EPSIZE / 2; } // Try to load some bytes if we can if (len) { UserToPMABufferCopy(sendBuf, VCOM_TX_ADDR, len); _SetEPTxCount(VCOM_TX_ENDP, len); countTx += len; _SetEPTxValid(VCOM_TX_ENDP); } return len; }
void Usb_SendData(u8 len) { //UserToPMABufferCopyENDP1(USB_TX_DATA,len); _SetEPTxCount(ENDP1, len); _SetEPTxStatus(ENDP1, EP_TX_VALID); }