-
-
Notifications
You must be signed in to change notification settings - Fork 160
Expand file tree
/
Copy pathCDCcomm.cpp
More file actions
93 lines (78 loc) · 2.37 KB
/
CDCcomm.cpp
File metadata and controls
93 lines (78 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* CDCcomm.cpp
*
* Created on: 17.11.2021
* Author: Yannick
*
* Contains functions to interface a usb CDC port
*/
#include "CDCcomm.h"
#include "tusb.h"
// Flag to trigger another send call
bool CDCcomm::usb_busy_retry = false;
std::string CDCcomm::remainingStrs[CFG_TUD_CDC] = {""};
std::string CDCcomm::tString;
cpp_freertos::BinarySemaphore CDCcomm::cdcSems[CFG_TUD_CDC] = {cpp_freertos::BinarySemaphore(true)};
CDCcomm::CDCcomm() {
}
CDCcomm::~CDCcomm() {
}
/**
* Global callback if cdc transfer is finished. Used to retry a failed transfer
*/
void CDCcomm::cdcFinished(uint8_t itf){
bool ret = cdcSems[itf].Give();
if (true != ret){
// FFB_LOGE("cdcSem give error\n");
return;
}
if(CDCcomm::usb_busy_retry && CDCcomm::remainingStrs[itf].length() > 0){
cdcSend(&CDCcomm::remainingStrs[itf], itf); // Retry with remaining string
}
if(CDCcomm::remainingStrs[itf].capacity() > 512){
CDCcomm::remainingStrs[itf].shrink_to_fit(); // Prevent permanent increase of size if a long command was buffered
}
}
/**
* Checks if data is remaining in a buffer to be sent
*/
uint32_t CDCcomm::remainingData(uint8_t itf){
return CDCcomm::remainingStrs[itf].size();
}
/**
* Clears a buffer
*/
void CDCcomm::clearRemainingBuffer(uint8_t itf){
CDCcomm::remainingStrs[itf].clear();
}
bool CDCcomm::connected(uint8_t itf){
return tud_cdc_n_connected(itf);
}
/**
* Sends a string via CDC
* If not everything can be sent it will be buffered for later in a new string
*/
uint16_t CDCcomm::cdcSend(std::string* reply,uint8_t itf){
if(!tud_ready() || reply->empty()){ // TODO check if connected when gui sets DTR
return 0;
}
cdcSems[itf].Take();
uint32_t bufferRemaining = tud_cdc_n_write_available(itf);
uint32_t cdc_sent = tud_cdc_n_write(itf,reply->c_str(), std::min<uint16_t>(reply->length(),bufferRemaining));
if(!usb_busy_retry){ // We did not retransmit so flush now. otherwise TUD will flush if we were in the callback before
int res = tud_cdc_n_write_flush(itf);
if (!res) {
FFB_LOGW("flush failed (res: %d, len=%d)", res, reply->length());
}
}
// If we can't write the whole reply copy remainder to send later
if(cdc_sent < reply->length()){
remainingStrs[itf] = reply->substr(cdc_sent);
usb_busy_retry = true;
remainingStrs[itf].shrink_to_fit();
}else{
usb_busy_retry = false;
remainingStrs[itf].clear();
}
return cdc_sent;
}