asked it to simplify the code
This commit is contained in:
+59
-75
@@ -75,7 +75,6 @@ the higher level `turboPmac` driver to manually call the `pmacFlush` function.
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <osiSock.h>
|
||||
#include <osiUnistd.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/poll.h>
|
||||
@@ -124,13 +123,11 @@ constexpr double SEND_RETRY_DELAY = 0.01;
|
||||
*/
|
||||
static int setNonBlock(SOCKET fd, int nonBlockFlag) {
|
||||
#if defined(vxWorks)
|
||||
int flags;
|
||||
flags = nonBlockFlag;
|
||||
int flags = nonBlockFlag;
|
||||
if (ioctl(fd, FIONBIO, (int)&flags) < 0)
|
||||
return -1;
|
||||
#elif defined(_WIN32)
|
||||
unsigned long int flags;
|
||||
flags = nonBlockFlag;
|
||||
unsigned long int flags = nonBlockFlag;
|
||||
if (socket_ioctl(fd, FIONBIO, &flags) < 0)
|
||||
return -1;
|
||||
#else
|
||||
@@ -148,10 +145,9 @@ static int setNonBlock(SOCKET fd, int nonBlockFlag) {
|
||||
}
|
||||
|
||||
pmacAsynIPPort::pmacAsynIPPort(const char *portName, const char *hostInfo)
|
||||
: asynPortDriver(
|
||||
portName, 1 /* maxAddr */, asynOctetMask | asynInt32Mask,
|
||||
0 /* interruptMask */, ASYN_CANBLOCK, 1 /* autoConnect */,
|
||||
0 /* priority */, 0 /* stackSize */),
|
||||
: asynPortDriver(portName, 1 /* maxAddr */, asynOctetMask | asynInt32Mask,
|
||||
0 /* interruptMask */, ASYN_CANBLOCK, 1 /* autoConnect */,
|
||||
0 /* priority */, 0 /* stackSize */),
|
||||
inBuf_(MAX_BUFFER_SIZE) {
|
||||
// The base class constructor mirrors drvAsynIPPortConfigure(portName,
|
||||
// hostInfo, priority, noAutoConnect) with ASYN_CANBLOCK and autoConnect
|
||||
@@ -196,7 +192,7 @@ void pmacAsynIPPort::parseHostInfo(const char *hostInfo) {
|
||||
|
||||
asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
|
||||
SOCKET fd;
|
||||
int i;
|
||||
int i = 1;
|
||||
char sockerrmsg[256];
|
||||
osiSockAddr farAddr;
|
||||
|
||||
@@ -237,15 +233,14 @@ asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
|
||||
if (setNonBlock(fd, 1) < 0) {
|
||||
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
|
||||
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
|
||||
"Can't set %s O_NONBLOCK option: %s",
|
||||
IPHostName_.c_str(), sockerrmsg);
|
||||
"Can't set %s O_NONBLOCK option: %s", IPHostName_.c_str(),
|
||||
sockerrmsg);
|
||||
epicsSocketDestroy(fd);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
{
|
||||
int connectResult =
|
||||
::connect(fd, &farAddr.sa, sizeof(farAddr.ia));
|
||||
int connectResult = ::connect(fd, &farAddr.sa, sizeof(farAddr.ia));
|
||||
if (connectResult < 0 &&
|
||||
(SOCKERRNO == SOCK_EWOULDBLOCK || SOCKERRNO == SOCK_EINPROGRESS)) {
|
||||
int msConnectTimeout;
|
||||
@@ -285,7 +280,6 @@ asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
|
||||
}
|
||||
}
|
||||
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof i) < 0) {
|
||||
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
|
||||
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
|
||||
@@ -336,14 +330,37 @@ asynStatus pmacAsynIPPort::disconnect(asynUser *pasynUser) {
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus pmacAsynIPPort::pollSocket(asynUser *pasynUser,
|
||||
struct pollfd *pollfd, int pollmsec,
|
||||
int *pollstatus) {
|
||||
epicsTimeStamp startTime;
|
||||
epicsTimeStamp endTime;
|
||||
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
while ((*pollstatus = poll(pollfd, 1, pollmsec)) < 0) {
|
||||
if (SOCKERRNO != SOCK_EINTR) {
|
||||
char sockerrmsg[256];
|
||||
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
|
||||
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
|
||||
"%s poll() failed: %s", IPHostName_.c_str(),
|
||||
sockerrmsg);
|
||||
return asynError;
|
||||
}
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000. > pollmsec)
|
||||
break;
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus pmacAsynIPPort::socketRead(asynUser *pasynUser, char *data,
|
||||
size_t maxchars, size_t *nbytesRead) {
|
||||
int thisRead;
|
||||
int readPollmsec;
|
||||
int pollstatus;
|
||||
asynStatus status = asynSuccess;
|
||||
char sockerrmsg[256];
|
||||
epicsTimeStamp startTime;
|
||||
epicsTimeStamp endTime;
|
||||
struct pollfd pollfd;
|
||||
|
||||
*nbytesRead = 0;
|
||||
if (fd_ == INVALID_SOCKET) {
|
||||
@@ -363,25 +380,11 @@ asynStatus pmacAsynIPPort::socketRead(asynUser *pasynUser, char *data,
|
||||
if (readPollmsec < 0)
|
||||
readPollmsec = -1;
|
||||
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
pollfd.fd = fd_;
|
||||
pollfd.events = POLLIN;
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
while (poll(&pollfd, 1, readPollmsec) < 0) {
|
||||
if (SOCKERRNO != SOCK_EINTR) {
|
||||
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
|
||||
epicsSnprintf(pasynUser->errorMessage,
|
||||
pasynUser->errorMessageSize, "Poll() failed: %s",
|
||||
sockerrmsg);
|
||||
return asynError;
|
||||
}
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000. >
|
||||
readPollmsec)
|
||||
break;
|
||||
}
|
||||
}
|
||||
pollfd.fd = fd_;
|
||||
pollfd.events = POLLIN;
|
||||
status = pollSocket(pasynUser, &pollfd, readPollmsec, &pollstatus);
|
||||
if (status != asynSuccess)
|
||||
return status;
|
||||
|
||||
thisRead = recv(fd_, data, (int)maxchars, 0);
|
||||
if (thisRead < 0) {
|
||||
@@ -419,10 +422,12 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
|
||||
asynStatus status = asynSuccess;
|
||||
int thisWrite;
|
||||
int writePollmsec;
|
||||
int pollstatus;
|
||||
epicsTimeStamp startTime;
|
||||
epicsTimeStamp endTime;
|
||||
int haveStartTime = 0;
|
||||
char sockerrmsg[256];
|
||||
struct pollfd pollfd;
|
||||
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s write.\n", IPHostName_.c_str());
|
||||
*nbytesTransferred = 0;
|
||||
@@ -439,25 +444,11 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
|
||||
if (writePollmsec < 0)
|
||||
writePollmsec = -1;
|
||||
for (;;) {
|
||||
int pollstatus;
|
||||
struct pollfd pollfd;
|
||||
pollfd.fd = fd_;
|
||||
pollfd.events = POLLOUT;
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
while ((pollstatus = poll(&pollfd, 1, writePollmsec)) < 0) {
|
||||
if (SOCKERRNO != SOCK_EINTR) {
|
||||
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
|
||||
epicsSnprintf(pasynUser->errorMessage,
|
||||
pasynUser->errorMessageSize,
|
||||
"%s poll() failed: %s", IPHostName_.c_str(),
|
||||
sockerrmsg);
|
||||
return asynError;
|
||||
}
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000 >
|
||||
writePollmsec)
|
||||
break;
|
||||
}
|
||||
status = pollSocket(pasynUser, &pollfd, writePollmsec, &pollstatus);
|
||||
if (status != asynSuccess)
|
||||
return status;
|
||||
if (pollstatus == 0) {
|
||||
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
|
||||
"%s poll() timed out", IPHostName_.c_str());
|
||||
@@ -504,8 +495,7 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
|
||||
break;
|
||||
}
|
||||
}
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW,
|
||||
"wrote %lu to %s, return %s.\n",
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW, "wrote %lu to %s, return %s.\n",
|
||||
(unsigned long)*nbytesTransferred, IPHostName_.c_str(),
|
||||
pasynManager->strStatus(status));
|
||||
return status;
|
||||
@@ -700,9 +690,9 @@ asynStatus pmacAsynIPPort::writeOctet(asynUser *pasynUser, const char *data,
|
||||
poutCmd_.wValue = data[0];
|
||||
poutCmd_.wIndex = 0;
|
||||
poutCmd_.wLength = htons(0);
|
||||
status = socketWrite(pasynUser,
|
||||
reinterpret_cast<const char *>(&poutCmd_),
|
||||
ETHERNET_CMD_HEADER, &nbytesActual);
|
||||
status =
|
||||
socketWrite(pasynUser, reinterpret_cast<const char *>(&poutCmd_),
|
||||
ETHERNET_CMD_HEADER, &nbytesActual);
|
||||
*nbytesTransfered = nbytesActual == ETHERNET_CMD_HEADER ? numchars : 0;
|
||||
} else {
|
||||
if (numchars > ETHERNET_DATA_SIZE) {
|
||||
@@ -743,9 +733,9 @@ asynStatus pmacAsynIPPort::writeOctet(asynUser *pasynUser, const char *data,
|
||||
poutCmd_.wIndex = 0;
|
||||
poutCmd_.wLength = htons(numchars);
|
||||
memcpy(poutCmd_.bData, data, numchars);
|
||||
status = socketWrite(pasynUser,
|
||||
reinterpret_cast<const char *>(&poutCmd_),
|
||||
numchars + ETHERNET_CMD_HEADER, &nbytesActual);
|
||||
status =
|
||||
socketWrite(pasynUser, reinterpret_cast<const char *>(&poutCmd_),
|
||||
numchars + ETHERNET_CMD_HEADER, &nbytesActual);
|
||||
if (nbytesActual > ETHERNET_CMD_HEADER)
|
||||
*nbytesTransfered = nbytesActual - ETHERNET_CMD_HEADER;
|
||||
else
|
||||
@@ -833,8 +823,8 @@ asynStatus pmacAsynIPPort::readOctet(asynUser *pasynUser, char *data,
|
||||
nbytesTransfered);
|
||||
}
|
||||
}
|
||||
status = readResponse(pasynUser, maxchars - nRead, &thisRead,
|
||||
eomReason);
|
||||
status =
|
||||
readResponse(pasynUser, maxchars - nRead, &thisRead, eomReason);
|
||||
initialRead = false;
|
||||
if (status != asynSuccess || thisRead == 0)
|
||||
break;
|
||||
@@ -880,19 +870,13 @@ asynStatus pmacAsynIPPort::flushOctet(asynUser *pasynUser) {
|
||||
asynStatus pmacAsynIPPort::writeInt32(asynUser *pasynUser, epicsInt32 value) {
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW, "pmacAsynIPPort::writeInt32\n");
|
||||
|
||||
if (pasynUser->reason == FLUSH_HARDWARE) {
|
||||
/*
|
||||
According to the Turbo PMAC user manual, p. 414:
|
||||
0 - failed 1 - success
|
||||
*/
|
||||
if (pmacFlush(pasynUser) == 1) {
|
||||
return asynSuccess;
|
||||
} else {
|
||||
return asynError;
|
||||
}
|
||||
} else {
|
||||
if (pasynUser->reason != FLUSH_HARDWARE)
|
||||
return asynPortDriver::writeInt32(pasynUser, value);
|
||||
}
|
||||
|
||||
/* Turbo PMAC User Manual, p. 414: 0 - failed, 1 - success */
|
||||
if (pmacFlush(pasynUser) == 1)
|
||||
return asynSuccess;
|
||||
return asynError;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
@@ -120,6 +120,16 @@ class HIDDEN pmacAsynIPPort : public asynPortDriver {
|
||||
asynStatus socketWrite(asynUser *pasynUser, const char *data,
|
||||
size_t numchars, size_t *nbytesWritten);
|
||||
|
||||
/**
|
||||
* @brief Poll the socket fd, retrying while poll() is interrupted by
|
||||
* EINTR.
|
||||
*
|
||||
* @return asynSuccess with *pollstatus holding poll()'s return value, or
|
||||
* asynError if poll() failed for a different reason.
|
||||
*/
|
||||
asynStatus pollSocket(asynUser *pasynUser, struct pollfd *pollfd,
|
||||
int pollmsec, int *pollstatus);
|
||||
|
||||
/**
|
||||
* @brief Read response data from the PMAC into the internal input buffer
|
||||
*
|
||||
|
||||
@@ -36,8 +36,6 @@ struct turboPmacControllerImpl {
|
||||
// Timeout for the communication process in seconds
|
||||
double comTimeout;
|
||||
|
||||
char lastResponse[sinqController::MAXBUF_];
|
||||
|
||||
// User for writing int32 values to the port driver.
|
||||
asynUser *pasynInt32SyncIOipPort;
|
||||
|
||||
@@ -46,6 +44,8 @@ struct turboPmacControllerImpl {
|
||||
int readConfig;
|
||||
int flushHardware;
|
||||
int limFromHardware;
|
||||
|
||||
char lastResponse[sinqController::MAXBUF_];
|
||||
};
|
||||
#define NUM_turboPmac_DRIVER_PARAMS 5
|
||||
|
||||
@@ -65,12 +65,12 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
pTurboPmacC_(
|
||||
std::make_unique<turboPmacControllerImpl>((turboPmacControllerImpl){
|
||||
.comTimeout = comTimeout,
|
||||
.lastResponse = {0},
|
||||
.pasynInt32SyncIOipPort = nullptr, // Populated in constructor
|
||||
.rereadEncoderPosition = 0, // Populated in constructor
|
||||
.readConfig = 0, // Populated in constructor
|
||||
.flushHardware = 0, // Populated in constructor
|
||||
.limFromHardware = 0, // Populated in constructor
|
||||
.lastResponse = {0},
|
||||
})) {
|
||||
// Initialization of local variables
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
Reference in New Issue
Block a user