Change API to require all calls be from the same context. (#78)

* Remove atomic driver and all uses of otPlatAtomic* in OpenThread.
* Change posix example to only use a single thread of execution.
This commit is contained in:
Jonathan Hui
2016-05-27 09:16:04 -07:00
parent 21e0e8aa92
commit 7d2e4a0267
26 changed files with 410 additions and 591 deletions
-1
View File
@@ -44,7 +44,6 @@ soc_LDADD = \
$(top_builddir)/src/cli/libopenthread-cli.a \
$(top_builddir)/examples/platform/posix/libopenthread-posix.a \
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
-lpthread \
$(NULL)
soc_SOURCES = \
+2 -16
View File
@@ -32,7 +32,6 @@
#include <openthread.h>
#include <cli/cli_serial.hpp>
#include <platform/atomic.h>
#include <platform.h>
struct gengetopt_args_info args_info;
@@ -45,32 +44,19 @@ void otSignalTaskletPending(void)
int main(int argc, char *argv[])
{
uint32_t atomic_state;
if (cmdline_parser(argc, argv, &args_info) != 0)
{
exit(1);
}
hwAlarmInit();
hwRadioInit();
hwRandomInit();
PlatformInit();
otInit();
sCliServer.Start();
while (1)
{
otProcessNextTasklet();
atomic_state = otPlatAtomicBegin();
if (!otAreTaskletsPending())
{
hwSleep();
}
otPlatAtomicEnd(atomic_state);
PlatformProcessDrivers();
}
return 0;
-1
View File
@@ -45,7 +45,6 @@ ncp_LDADD = \
$(top_builddir)/src/core/libopenthread.a \
$(top_builddir)/examples/platform/posix/libopenthread-posix.a \
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
-lpthread \
$(NULL)
ncp_SOURCES = main.cpp
+2 -18
View File
@@ -30,7 +30,6 @@
#include <platform/posix/cmdline.h>
#include <ncp/ncp.hpp>
#include <platform/atomic.h>
#include <platform.h>
struct gengetopt_args_info args_info;
@@ -43,19 +42,12 @@ void otSignalTaskletPending(void)
int main(int argc, char *argv[])
{
uint32_t atomic_state;
memset(&args_info, 0, sizeof(args_info));
if (cmdline_parser(argc, argv, &args_info) != 0)
{
exit(1);
}
hwAlarmInit();
hwRadioInit();
hwRandomInit();
PlatformInit();
otInit();
sNcp.Start();
@@ -63,15 +55,7 @@ int main(int argc, char *argv[])
while (1)
{
otProcessNextTasklet();
atomic_state = otPlatAtomicBegin();
if (!otAreTaskletsPending())
{
hwSleep();
}
otPlatAtomicEnd(atomic_state);
PlatformProcessDrivers();
}
return 0;
+1 -1
View File
@@ -52,9 +52,9 @@ libopenthread_posix_a_CXXFLAGS = \
libopenthread_posix_a_SOURCES = \
alarm.c \
atomic.c \
cmdline.c \
logging.c \
platform.c \
radio.cpp \
random.c \
serial.c \
+32 -47
View File
@@ -26,7 +26,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -34,20 +33,13 @@
#include <platform/alarm.h>
static void *alarm_thread(void *arg);
static bool s_is_running = false;
static uint32_t s_alarm = 0;
static struct timeval s_start;
static pthread_t s_thread;
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
void hwAlarmInit(void)
void PlatformAlarmInit(void)
{
gettimeofday(&s_start, NULL);
pthread_create(&s_thread, NULL, alarm_thread, NULL);
}
uint32_t otPlatAlarmGetNow(void)
@@ -62,65 +54,58 @@ uint32_t otPlatAlarmGetNow(void)
void otPlatAlarmStartAt(uint32_t t0, uint32_t dt)
{
pthread_mutex_lock(&s_mutex);
s_alarm = t0 + dt;
s_is_running = true;
pthread_mutex_unlock(&s_mutex);
pthread_cond_signal(&s_cond);
}
void otPlatAlarmStop(void)
{
pthread_mutex_lock(&s_mutex);
s_is_running = false;
pthread_mutex_unlock(&s_mutex);
}
void *alarm_thread(void *arg)
void PlatformAlarmUpdateTimeout(struct timeval *aTimeout)
{
int32_t remaining;
struct timeval tva;
struct timeval tvb;
struct timespec ts;
while (1)
if (aTimeout == NULL)
{
pthread_mutex_lock(&s_mutex);
return;
}
if (!s_is_running)
if (s_is_running)
{
remaining = s_alarm - otPlatAlarmGetNow();
if (remaining > 0)
{
// alarm is not running, wait indefinitely
pthread_cond_wait(&s_cond, &s_mutex);
pthread_mutex_unlock(&s_mutex);
aTimeout->tv_sec = remaining / 1000;
aTimeout->tv_usec = (remaining % 1000) * 1000;
}
else
{
// alarm is running
remaining = s_alarm - otPlatAlarmGetNow();
aTimeout->tv_sec = 0;
aTimeout->tv_usec = 0;
}
}
else
{
aTimeout->tv_sec = 10;
aTimeout->tv_usec = 0;
}
}
if (remaining > 0)
{
// alarm has not passed, wait
gettimeofday(&tva, NULL);
tvb.tv_sec = remaining / 1000;
tvb.tv_usec = (remaining % 1000) * 1000;
timeradd(&tva, &tvb, &tva);
void PlatformAlarmProcess(void)
{
int32_t remaining;
ts.tv_sec = tva.tv_sec;
ts.tv_nsec = tva.tv_usec * 1000;
if (s_is_running)
{
remaining = s_alarm - otPlatAlarmGetNow();
pthread_cond_timedwait(&s_cond, &s_mutex, &ts);
pthread_mutex_unlock(&s_mutex);
}
else
{
// alarm has passed, signal
s_is_running = false;
pthread_mutex_unlock(&s_mutex);
otPlatAlarmSignalFired();
}
if (remaining <= 0)
{
s_is_running = false;
otPlatAlarmFired();
}
}
return NULL;
}
@@ -26,28 +26,51 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <pthread.h>
#include <stdio.h>
/**
* @file
* @brief
* This file includes the platform-specific initializers.
*/
#include <platform/atomic.h>
#include <platform/posix/platform.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/time.h>
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
#include <openthread.h>
#include <platform/alarm.h>
#include "platform.h"
uint32_t otPlatAtomicBegin(void)
void PlatformInit(void)
{
pthread_mutex_lock(&s_mutex);
return 0;
PlatformAlarmInit();
PlatformRadioInit();
PlatformRandomInit();
}
void otPlatAtomicEnd(uint32_t state)
void PlatformProcessDrivers(void)
{
pthread_mutex_unlock(&s_mutex);
pthread_cond_signal(&s_cond);
}
fd_set read_fds;
fd_set write_fds;
int max_fd = -1;
struct timeval timeout;
int rval;
void hwSleep(void)
{
pthread_cond_wait(&s_cond, &s_mutex);
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
PlatformSerialUpdateFdSet(&read_fds, &write_fds, &max_fd);
PlatformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
PlatformAlarmUpdateTimeout(&timeout);
if (!otAreTaskletsPending())
{
rval = select(max_fd + 1, &read_fds, &write_fds, NULL, &timeout);
assert(rval >= 0 && errno != ETIME);
}
PlatformSerialProcess();
PlatformRadioProcess();
PlatformAlarmProcess();
}
+64 -4
View File
@@ -36,34 +36,94 @@
#define PLATFORM_H_
#include <stdint.h>
#include <sys/select.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This method performs all platform-specific initialization.
*
*/
void PlatformInit(void);
/**
* This method performs all platform-specific processing.
*
*/
void PlatformProcessDrivers(void);
/**
* This method initializes the alarm service used by OpenThread.
*
*/
void hwAlarmInit(void);
void PlatformAlarmInit(void);
/**
* This method retrieves the time remaining until the alarm fires.
*
* @param[out] aTimeval A pointer to the timeval struct.
*
*/
void PlatformAlarmUpdateTimeout(struct timeval *tv);
/**
* This method performs alarm driver processing.
*
*/
void PlatformAlarmProcess(void);
/**
* This method initializes the radio service used by OpenThread.
*
*/
void hwRadioInit(void);
void PlatformRadioInit(void);
/**
* This method updates the file descriptor sets with file descriptors used by the radio driver.
*
* @param[inout] aReadFdSet A pointer to the read file descriptors.
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
* @param[inout] aMaxFd A pointer to the max file descriptor.
*
*/
void PlatformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
/**
* This method performs radio driver processing.
*
*/
void PlatformRadioProcess(void);
/**
* This method initializes the random number service used by OpenThread.
*
*/
void hwRandomInit(void);
void PlatformRandomInit(void);
/**
* This method updates the file descriptor sets with file descriptors used by the serial driver.
*
* @param[inout] aReadFdSet A pointer to the read file descriptors.
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
* @param[inout] aMaxFd A pointer to the max file descriptor.
*
*/
void PlatformSerialUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
/**
* This method performs radio driver processing.
*
*/
void PlatformSerialProcess(void);
/**
* This method puts the thread executing OpenThread to sleep.
*
*/
void hwSleep(void);
void PlatformSleep(void);
#ifdef __cplusplus
} // extern "C"
+168 -186
View File
@@ -28,8 +28,8 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>
#include <netinet/in.h>
#include <poll.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,7 +70,8 @@ struct RadioMessage
uint8_t mPsdu[Mac::Frame::kMTU];
} __attribute__((packed));
static void *phy_receive_thread(void *arg);
static void radioSendAck(void);
static void radioProcessFrame(void);
static PhyState s_state = kStateDisabled;
static RadioPacket *s_receive_frame = NULL;
@@ -82,9 +83,6 @@ static uint8_t s_extended_address[8];
static uint16_t s_short_address;
static uint16_t s_panid;
static pthread_t s_pthread;
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_condition_variable = PTHREAD_COND_INITIALIZER;
static int s_sockfd;
ThreadError otPlatRadioSetPanId(uint16_t panid)
@@ -109,7 +107,7 @@ ThreadError otPlatRadioSetShortAddress(uint16_t address)
return kThreadError_None;
}
void hwRadioInit()
void PlatformRadioInit(void)
{
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
@@ -119,58 +117,44 @@ void hwRadioInit()
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
pthread_create(&s_pthread, NULL, &phy_receive_thread, NULL);
}
ThreadError otPlatRadioEnable()
ThreadError otPlatRadioEnable(void)
{
ThreadError error = kThreadError_None;
pthread_mutex_lock(&s_mutex);
VerifyOrExit(s_state == kStateDisabled, error = kThreadError_Busy);
s_state = kStateSleep;
pthread_cond_signal(&s_condition_variable);
exit:
pthread_mutex_unlock(&s_mutex);
return error;
}
ThreadError otPlatRadioDisable()
ThreadError otPlatRadioDisable(void)
{
pthread_mutex_lock(&s_mutex);
s_state = kStateDisabled;
pthread_cond_signal(&s_condition_variable);
pthread_mutex_unlock(&s_mutex);
return kThreadError_None;
}
ThreadError otPlatRadioSleep()
ThreadError otPlatRadioSleep(void)
{
ThreadError error = kThreadError_None;
pthread_mutex_lock(&s_mutex);
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
s_state = kStateSleep;
pthread_cond_signal(&s_condition_variable);
exit:
pthread_mutex_unlock(&s_mutex);
return error;
}
ThreadError otPlatRadioIdle()
ThreadError otPlatRadioIdle(void)
{
ThreadError error = kThreadError_None;
pthread_mutex_lock(&s_mutex);
switch (s_state)
{
case kStateSleep:
s_state = kStateIdle;
pthread_cond_signal(&s_condition_variable);
break;
case kStateIdle:
@@ -180,7 +164,6 @@ ThreadError otPlatRadioIdle()
case kStateTransmit:
case kStateAckWait:
s_state = kStateIdle;
pthread_cond_signal(&s_condition_variable);
break;
case kStateDisabled:
@@ -189,7 +172,6 @@ ThreadError otPlatRadioIdle()
}
exit:
pthread_mutex_unlock(&s_mutex);
return error;
}
@@ -197,32 +179,135 @@ ThreadError otPlatRadioReceive(RadioPacket *packet)
{
ThreadError error = kThreadError_None;
pthread_mutex_lock(&s_mutex);
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
s_state = kStateListen;
pthread_cond_signal(&s_condition_variable);
s_receive_frame = packet;
exit:
pthread_mutex_unlock(&s_mutex);
return error;
}
ThreadError otPlatRadioTransmit(RadioPacket *packet)
{
ThreadError error = kThreadError_None;
struct sockaddr_in sockaddr;
RadioMessage message;
pthread_mutex_lock(&s_mutex);
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
s_state = kStateTransmit;
pthread_cond_signal(&s_condition_variable);
s_transmit_frame = packet;
s_data_pending = false;
exit:
return error;
}
int8_t otPlatRadioGetNoiseFloor(void)
{
return 0;
}
otRadioCaps otPlatRadioGetCaps(void)
{
return kRadioCapsNone;
}
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
{
ThreadError error = kThreadError_None;
VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
s_state = kStateIdle;
if (rxPending != NULL)
{
*rxPending = s_data_pending;
}
exit:
return error;
}
void radioReceive(void)
{
RadioPacket receive_frame;
RadioMessage message;
uint8_t tx_sequence, rx_sequence;
uint8_t command_id;
int rval;
VerifyOrExit(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen ||
s_state == kStateAckWait, ;);
rval = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
assert(rval >= 0);
switch (s_state)
{
case kStateDisabled:
case kStateSleep:
case kStateIdle:
case kStateTransmit:
break;
case kStateAckWait:
receive_frame.mLength = rval - 1;
memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
{
break;
}
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
if (tx_sequence != rx_sequence)
{
break;
}
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
{
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
if (command_id == Mac::Frame::kMacCmdDataRequest)
{
s_data_pending = true;
}
}
s_state = kStateIdle;
otPlatRadioTransmitDone(s_data_pending, kThreadError_None);
break;
case kStateListen:
if (s_receive_frame->mChannel != message.mChannel)
{
break;
}
s_state = kStateReceive;
s_receive_frame->mLength = rval - 1;
memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
radioProcessFrame();
break;
case kStateReceive:
assert(false);
break;
}
exit:
return;
}
int radioTransmit(void)
{
struct sockaddr_in sockaddr;
RadioMessage message;
int rval;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
@@ -238,7 +323,9 @@ ThreadError otPlatRadioTransmit(RadioPacket *packet)
}
sockaddr.sin_port = htons(9000 + i);
sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
rval = sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr,
sizeof(sockaddr));
assert(rval >= 0);
}
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
@@ -247,154 +334,56 @@ ThreadError otPlatRadioTransmit(RadioPacket *packet)
}
else
{
otPlatRadioSignalTransmitDone();
s_state = kStateIdle;
otPlatRadioTransmitDone(false, kThreadError_None);
}
exit:
pthread_mutex_unlock(&s_mutex);
return error;
return rval;
}
int8_t otPlatRadioGetNoiseFloor()
void PlatformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
{
if (aReadFdSet != NULL &&
(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen || s_state == kStateAckWait))
{
FD_SET(s_sockfd, aReadFdSet);
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
{
*aMaxFd = s_sockfd;
}
}
if (aWriteFdSet != NULL && s_state == kStateTransmit)
{
FD_SET(s_sockfd, aWriteFdSet);
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
{
*aMaxFd = s_sockfd;
}
}
}
int PlatformRadioProcess(void)
{
const int flags = POLLRDNORM | POLLERR | POLLNVAL | POLLHUP;
struct pollfd pollfd = { s_sockfd, flags, 0 };
if (poll(&pollfd, 1, 0) > 0 && (pollfd.revents & flags) != 0)
{
radioReceive();
}
if (s_state == kStateTransmit)
{
radioTransmit();
}
return 0;
}
otRadioCaps otPlatRadioGetCaps()
{
return kRadioCapsNone;
}
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
{
ThreadError error = kThreadError_None;
VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
pthread_mutex_lock(&s_mutex);
s_state = kStateIdle;
pthread_cond_signal(&s_condition_variable);
pthread_mutex_unlock(&s_mutex);
if (rxPending != NULL)
{
*rxPending = s_data_pending;
}
exit:
return error;
}
void *phy_receive_thread(void *arg)
{
fd_set fds;
int rval;
RadioPacket receive_frame;
int length;
uint8_t tx_sequence, rx_sequence;
uint8_t command_id;
RadioMessage message;
while (1)
{
FD_ZERO(&fds);
FD_SET(s_sockfd, &fds);
rval = select(s_sockfd + 1, &fds, NULL, NULL, NULL);
if (rval < 0 || !FD_ISSET(s_sockfd, &fds))
{
continue;
}
pthread_mutex_lock(&s_mutex);
while (s_state == kStateIdle || s_state == kStateTransmit)
{
pthread_cond_wait(&s_condition_variable, &s_mutex);
}
switch (s_state)
{
case kStateDisabled:
case kStateIdle:
case kStateSleep:
recvfrom(s_sockfd, NULL, 0, 0, NULL, NULL);
break;
case kStateTransmit:
break;
case kStateAckWait:
length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
receive_frame.mLength = length - 1;
memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
if (length < 0)
{
assert(false);
}
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
{
break;
}
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
if (tx_sequence != rx_sequence)
{
break;
}
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
{
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
if (command_id == Mac::Frame::kMacCmdDataRequest)
{
s_data_pending = true;
}
}
otPlatRadioSignalTransmitDone();
break;
case kStateListen:
length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
if (s_receive_frame->mChannel != message.mChannel)
{
break;
}
s_state = kStateReceive;
s_receive_frame->mLength = length - 1;
memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
otPlatRadioSignalReceiveDone();
while (s_state == kStateReceive)
{
pthread_cond_wait(&s_condition_variable, &s_mutex);
}
break;
case kStateReceive:
assert(false);
break;
}
pthread_mutex_unlock(&s_mutex);
}
return NULL;
}
void send_ack()
void radioSendAck(void)
{
Mac::Frame *ack_frame;
RadioMessage message;
@@ -426,17 +415,14 @@ void send_ack()
}
}
ThreadError otPlatRadioHandleReceiveDone()
void radioProcessFrame(void)
{
ThreadError error = kThreadError_None;
Mac::Frame *receive_frame;
uint16_t dstpan;
Mac::Address dstaddr;
VerifyOrExit(s_state == kStateReceive, error = kThreadError_InvalidState);
receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
receive_frame->GetDstAddr(dstaddr);
switch (dstaddr.mLength)
@@ -468,21 +454,17 @@ ThreadError otPlatRadioHandleReceiveDone()
// generate acknowledgment
if (reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetAckRequest())
{
send_ack();
radioSendAck();
}
exit:
pthread_mutex_lock(&s_mutex);
if (s_state != kStateDisabled)
{
s_state = kStateIdle;
}
pthread_cond_signal(&s_condition_variable);
pthread_mutex_unlock(&s_mutex);
return error;
otPlatRadioReceiveDone(error);
}
#ifdef __cplusplus
+1 -1
View File
@@ -41,7 +41,7 @@ extern struct gengetopt_args_info args_info;
static uint32_t s_state = 1;
void hwRandomInit(void)
void PlatformRandomInit(void)
{
s_state = args_info.nodeid_arg;
}
+39 -44
View File
@@ -26,9 +26,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <poll.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
@@ -37,8 +37,6 @@
#include <platform/posix/cmdline.h>
#include <platform/serial.h>
static void *serial_receive_thread(void *arg);
#ifdef OPENTHREAD_TARGET_LINUX
int posix_openpt(int oflag);
int grantpt(int fildes);
@@ -49,20 +47,20 @@ char *ptsname(int fd);
extern struct gengetopt_args_info args_info;
static uint8_t s_receive_buffer[128];
static const uint8_t *s_write_buffer;
static uint16_t s_write_length;
static int s_in_fd;
static int s_out_fd;
static pthread_t s_pthread;
static sem_t *s_semaphore;
static struct termios original_stdin_termios;
static struct termios original_stdout_termios;
static void restore_stdin_termios()
static void restore_stdin_termios(void)
{
tcsetattr(s_in_fd, TCSAFLUSH, &original_stdin_termios);
}
static void restore_stdout_termios()
static void restore_stdout_termios(void)
{
tcsetattr(s_out_fd, TCSAFLUSH, &original_stdout_termios);
}
@@ -72,7 +70,6 @@ ThreadError otPlatSerialEnable(void)
ThreadError error = kThreadError_None;
struct termios termios;
char *path;
char cmd[256];
if (args_info.stdserial_given == 1)
{
@@ -171,10 +168,6 @@ ThreadError otPlatSerialEnable(void)
VerifyOrExit(tcsetattr(s_out_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
}
snprintf(cmd, sizeof(cmd), "thread_serial_semaphore_%d", args_info.nodeid_arg);
s_semaphore = sem_open(cmd, O_CREAT, 0644, 0);
pthread_create(&s_pthread, NULL, &serial_receive_thread, NULL);
return error;
exit:
@@ -197,54 +190,56 @@ ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength)
{
ThreadError error = kThreadError_None;
VerifyOrExit(write(s_out_fd, aBuf, aBufLength) >= 0, error = kThreadError_Error);
otPlatSerialSignalSendDone();
VerifyOrExit(s_write_length == 0, error = kThreadError_Busy);
s_write_buffer = aBuf;
s_write_length = aBufLength;
exit:
return error;
}
void otPlatSerialHandleSendDone(void)
void PlatformSerialUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
{
}
void *serial_receive_thread(void *aContext)
{
fd_set fds;
int rval;
while (1)
if (aReadFdSet != NULL)
{
FD_ZERO(&fds);
FD_SET(s_in_fd, &fds);
FD_SET(s_in_fd, aReadFdSet);
rval = select(s_in_fd + 1, &fds, NULL, NULL, NULL);
if (rval >= 0 && FD_ISSET(s_in_fd, &fds))
if (aMaxFd != NULL && *aMaxFd < s_in_fd)
{
otPlatSerialSignalReceive();
sem_wait(s_semaphore);
*aMaxFd = s_in_fd;
}
}
return NULL;
if (aWriteFdSet != NULL && s_write_length > 0)
{
FD_SET(s_out_fd, aWriteFdSet);
if (aMaxFd != NULL && *aMaxFd < s_out_fd)
{
*aMaxFd = s_out_fd;
}
}
}
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength)
void PlatformSerialProcess(void)
{
size_t length;
const int flags = POLLRDNORM | POLLERR | POLLNVAL | POLLHUP;
struct pollfd pollfd = { s_in_fd, flags, 0 };
int rval;
length = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
if (aBufLength != NULL)
if (poll(&pollfd, 1, 0) > 0 && (pollfd.revents & flags) != 0)
{
*aBufLength = length;
rval = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
assert(rval >= 0);
otPlatSerialReceived(s_receive_buffer, rval);
}
return s_receive_buffer;
}
void otPlatSerialHandleReceiveDone(void)
{
sem_post(s_semaphore);
if (s_write_length > 0)
{
rval = write(s_out_fd, s_write_buffer, s_write_length);
assert(rval >= 0);
s_write_length = 0;
otPlatSerialSendDone();
}
}