///
#include "evdev.h"
#include <stdexcept>
+#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
throw std::invalid_argument("poll_fds() called with zero-size array.");
}
- std::size_t
- EvDev::ready()
- {
- int length = 0;
-
- if ( ioctl(fd, FIONREAD, &length) < 0 )
- do_throw(errno, name, special_file, "ioctl FIONREAD");
-
- return length / sizeof(input_event);
- }
-
std::size_t
EvDev::read_events(input_event * data, std::size_t count)
{
const int result = read(fd, data, count * sizeof(*data));
- if ( result < 0 )
- do_throw(errno, name, special_file, "read");
- return result / sizeof(*data);
+ if ( result < 0 ) {
+ if ( errno == EAGAIN ) {
+ return 0;
+ }
+ else
+ do_throw(errno, name, special_file, "read");
+ }
+ else
+ return result / sizeof(*data);
}
EvDev::EvDev(const char * _name)
static std::size_t count;
static device_enumeration * enumeration = 0;
- if ( (fd = open(name, O_RDWR) >= 0 ) ) {
+ if ( (fd = open(name, O_RDWR|O_NONBLOCK) >= 0 ) ) {
special_file = strdup(name);
return;
}
for ( std::size_t i = 0; i < count; i++ ) {
if ( strncmp(name, enumeration[i].name, length) == 0 ) {
special_file = strdup(enumeration[i].special_file);
- fd = open(special_file, O_RDWR);
+ fd = open(special_file, O_RDWR|O_NONBLOCK);
if ( fd < 0 )
do_throw(errno, name, special_file, "open");
PTT_EvDev::PTT_EvDev(const char * _parameters)
: PTTInput("evdev", _parameters), dev(0), button_index(0), pressed(false),
- changed(false)
+ changed(true)
{
char * p = strdup(parameters);
char * number = index(p, ',');
void
PTT_EvDev::process_events()
{
- while ( dev->ready() > 0 ) {
- input_event events[10];
-
- const std::size_t count = dev->read_events(
- events,
- sizeof(events) / sizeof(*events));
+ int count;
+ input_event events[10];
+ while ( (count = dev->read_events(
+ events,
+ sizeof(events) / sizeof(*events)))
+ > 0 ) {
+
for ( std::size_t i = 0; i < count; i++ ) {
const input_event * const event = &events[i];
if ( event->type == EV_KEY && event->code == button_index ) {
switch ( event->value ) {
case 0:
- if ( pressed )
- changed = true;
- pressed = false;
+ changed = true;
+ pressed = false;
break;
case 1:
- if ( !pressed )
- changed = true;
+ changed = true;
pressed = true;
break;
- default:
- ;
- }
+ default:
+ ;
+ }
}
}
}
std::size_t
PTT_EvDev::ready()
{
- return dev->ready();
+ process_events();
+ if ( changed )
+ return 1;
+ else
+ return 0;
}
bool
PTT_EvDev::state()
{
- process_events();
changed = false;
return pressed;
}
private:
const std::size_t FIFOSize = MaximumFrameSamples * sizeof(int16_t) * 2;
Interfaces * const i;
- bool begin_receive;
- bool begin_transmit;
FIFO codec_fifo;
FIFO in_fifo;
FIFO out_fifo;
int poll_fd_count;
- bool ptt_digital;
- bool ptt_ssb;
- bool started;
PollType poll_fds[100];
// Disable copy constructor and operator=().
bool add_poll_device(IODevice * device);
NORETURN void do_throw(int error, const char * message);
- void key_down();
- void key_up();
void receive();
void reset();
void transmit_digital();
};
Run::Run(Interfaces * interfaces)
- : i(interfaces), begin_receive(true), begin_transmit(false),
+ : i(interfaces),
codec_fifo(FIFOSize), in_fifo(FIFOSize),
- out_fifo(FIFOSize), poll_fd_count(0), ptt_digital(false), ptt_ssb(false),
- started(false)
+ out_fifo(FIFOSize), poll_fd_count(0)
{
reset();
-
- // FIX: This needs to be done at the start of the receive or transmit
- // loop, so that only the necessary devices will be polled.
- if ( !add_poll_device(i->receiver) )
- add_poll_device(i->loudspeaker);
- if ( !add_poll_device(i->microphone) )
- add_poll_device(i->transmitter);
- add_poll_device(i->ptt_input_digital);
- add_poll_device(i->ptt_input_ssb);
- add_poll_device(i->text_input);
- add_poll_device(i->user_interface);
}
Run::~Run()
&poll_fds[poll_fd_count],
space - poll_fd_count);
- if ( result >= 0 ) {
- const int new_size = poll_fd_count + result;
-
- if ( new_size < space ) {
- poll_fd_count = new_size;
- return new_size > 0;
- }
- else
- do_throw(0, "Too many file descriptors for poll");
- }
- else {
+ if ( result > 0 )
+ poll_fd_count += result;
+ else if ( result < 0 ) {
std::ostringstream str;
device->print(str);
void
Run::reset()
{
- started = false;
in_fifo.reset();
codec_fifo.reset();
out_fifo.reset();
}
- void
- Run::key_down() {
- if ( i->keying_output->ready() ) {
- i->keying_output->key(true);
- begin_transmit = false;
- }
- else {
- std::cerr << "Keying output is stalled." << std::endl;
- }
- }
-
- void
- Run::key_up()
- {
- if ( i->keying_output->ready() ) {
- i->keying_output->key(false);
- begin_receive = false;
- }
- else {
- std::cerr << "Keying output is stalled." << std::endl;
- }
- }
-
// FIX: Parallelize the modem and codec into their own threads. Make the
// FIFO do locking.
void
out_samples * 2),
out_samples);
- if ( result > 0 ) {
- started = true;
+ if ( result > 0 )
out_fifo.get_done(result * 2);
- }
else if ( result < 0 )
std::cerr << "Loudspeaker I/O error: " << strerror(errno) << std::endl;
}
void
Run::run()
{
- for ( ; ; ) {
- receive();
+ add_poll_device(i->ptt_input_digital);
+ add_poll_device(i->ptt_input_ssb);
- for ( int j = 0; j < poll_fd_count; j++ )
+ for ( ; ; ) {
+ for ( int j = 0; j < poll_fd_count; j++ ) {
poll_fds[j].revents = 0;
+ poll_fds[j].events = POLLIN;
+ }
- const int result = IODevice::poll(
- poll_fds,
- poll_fd_count,
- AudioFrameDuration);
+
+ const int result = IODevice::poll(poll_fds, poll_fd_count, 1000);
if ( result < 0 )
do_throw(result, "Poll");
+
+ if ( i->ptt_input_digital->ready() ) {
+ std::cerr << "Digital: " << i->ptt_input_digital->state() << std::endl;
+ }
+ if ( i->ptt_input_ssb->ready() ) {
+ std::cerr << "SSB: " << i->ptt_input_ssb->state() << std::endl;
+ }
}
}