DevSlashLirc
Mode2LircDevice.cpp
Go to the documentation of this file.
1 #include "Mode2LircDevice.h"
2 #include "LircT.h"
3 
4 #include <unistd.h>
5 #include <errno.h>
6 #include <sys/ioctl.h>
7 #include <string.h>
8 #include <poll.h>
9 
10 static const int IOCTL_OK = 0;
11 static const int IOCTL_ERROR = -1;
12 
13 Mode2LircDevice::Mode2LircDevice(const char *path, milliseconds_t beginTimeout, size_t captureSize_, milliseconds_t endTimeout_)
14  : LircDevice(path, beginTimeout),endTimeout(endTimeout_),captureSize(captureSize_) {
15 }
16 
18  bool status = LircDevice::open();
19  if (!status)
20  return false;
21 
22  if (recordingMode != LIRC_MODE_MODE2) {
23  std::cerr << "This is not a mode2 device!" << std::endl;
24  valid = false;
25  return false;
26  }
27 
28  if (canGetRecResolution()) {
29  uint32_t res;
30  int status = ::ioctl(fileDescriptor, LIRC_GET_REC_MODE, &res);
31  if (status != IOCTL_OK) {
32  std::cerr << "Error: " << status << std::endl;
33  return false;
34  }
35  resolution = (microseconds_t) res;
36  } else
37  resolution = (microseconds_t) INVALID;
38 
39  setRecTimeout(1000U * endTimeout); // do not care to check status
40  setRecTimeoutReports(true); // do not care to check status
41 
42  return true;
43 }
44 
45 void Mode2LircDevice::report(std::ostream& stream) const {
46  stream << "Filename \"" << fileName << "\"" << std::endl;
47  if (!reportValidity())
48  return;
49 
50  stream << "recording mode: mode2" << std::endl;
51  if (resolution != INVALID)
52  stream << "resolution = " << resolution << std::endl;
53  else if (longReport)
54  stream << "resolution: not available" << std::endl;
55 
56  LircDevice::report(stream);
57 
58  LircDevice::report("canSetSendCarrier", canSetSendCarrier(), stream);
59  //LircDevice::report("canSetSendDutyCycle", canSetSendDutyCycle(), stream);
60  LircDevice::report("canGetRecResolution", canGetRecResolution(), stream);
61 }
62 
68 lirc_t Mode2LircDevice::read(int timeout) {
69  if (!canRecMode2()) {
70  return 0;
71  }
72 
73  pollfd pfd = {
74  .fd = fileDescriptor,
75  .events = POLLIN,
76  .revents = 0
77  };
78  int rc = poll(&pfd, 1, timeout ? timeout : -1);
79  if (rc < 0)
80  return 0;
81  if (rc == 0)
82  return LircT::LircTType::TIMEOUT;
83 
84  lirc_t data;
85  ssize_t actualLength = ::read(fileDescriptor, &data, sizeof(lirc_t));
86  return actualLength == sizeof(lirc_t) ? data : 0;
87 }
88 
91  unsigned index = 0;
92  while (index < captureSize) {
93  lirc_t t = read(index == 0 ? beginTimeout : endTimeout);
94  if (t == 0)
95  return new IrSequence();
96 
97  LircT lircT(t);
98  if (lircT.isTerminal(t)) {
99  if (index > 0)
100  data[index++] = replacementEndingSilence;
101  break;
102  }
103 
104  if (index > 0 || lircT.isPulse()) // ignore leading spaces
105  data[index++] = lircT.getDuration(t);
106  }
107  if (index == 0)
108  return new IrSequence();
109 
110  microseconds_t* newData = new microseconds_t[index];
111  for (unsigned j = 0; j < index; j++)
112  newData[j] = data[j];
113  return new IrSequence(newData, index);
114 }
115 
116 void Mode2LircDevice::mode2dump(std::ostream& stream) {
117  while (true) {
118  lirc_t t = read(0);
119  if (t == 0) {
120  std::cerr << "0 received" << std::endl;
121  return;
122  }
123  LircT::dump(t, stream);
124  stream << std::endl;
125  }
126 }
127 
128 int Mode2LircDevice::write(const uint32_t *data, size_t length) {
129  if (!canSendPulse())
130  return ENOTSUP;
131 
132  return ::write(fileDescriptor, data, length);
133 }
134 
135 bool Mode2LircDevice::sendOdd(const lirc_t *data, unsigned length) {
136  if (!canSendPulse())
137  return false;
138 
139  size_t toSend = length * sizeof(lirc_t);
140  size_t sent = 0;
141 
142  while (sent < toSend) {
143  int n = ::write(fileDescriptor, data + sent/sizeof(lirc_t), toSend - sent);
144  if (n < 0)
145  return false;
146  sent += n;
147  }
148  return true;
149 }
150 
151 bool Mode2LircDevice::send(const lirc_t *data, unsigned length) {
152  if (length % 2 != 0)
153  return sendOdd(data, length);
154 
155  lirc_t newData[length + 1];
156  memcpy(newData, data, length*sizeof(lirc_t));
157  newData[length] = 1;
158  return sendOdd(newData, length+1);
159 }
160 
161 bool Mode2LircDevice::send(const IrSequence& irSequence) {
162  return send((lirc_t*)irSequence.getDurations(), irSequence.getLength());
163 }
164 
165 bool Mode2LircDevice::send(const lirc_t *data, unsigned length, frequency_t frequency) {
166  if (canSetSendCarrier()) {
167  int status = setSendCarrier(frequency);
168  if (status == IOCTL_ERROR) {
169  std::cerr << "Could not set sending frequency" << std::endl;
170  return false;
171  }
172  } else {
173  std::cerr << "Device does not support setting sending frequency" << std::endl;
174  return false;
175  }
176  return send(data, length);
177 }
bool canSendPulse() const
Definition: LircDevice.h:82
int fileDescriptor
Definition: LircDevice.h:31
uint32_t frequency_t
Largest milliseconds_t number possible.
Definition: InfraredTypes.h:38
bool valid
Definition: LircDevice.h:29
uint32_t recordingMode
Definition: LircDevice.h:33
void dump(std::ostream &stream=std::cout) const
Definition: LircT.cpp:19
const char * fileName
Definition: LircDevice.h:30
lirc_t read(int timeout)
Reads exactly one duration.
virtual bool open()
Definition: LircDevice.cpp:21
int ioctl(uint32_t cmd, uint32_t arg)
Definition: LircDevice.cpp:98
const microseconds_t * getDurations() const
Definition: IrSequence.h:60
int setRecTimeoutReports(bool enable)
Enable or disable timeout packages.
Definition: LircDevice.h:124
virtual bool open()
bool reportValidity(std::ostream &stream=std::cout) const
Definition: LircDevice.cpp:138
bool send(const lirc_t *data, unsigned length)
Mid-level sending routine.
uint32_t milliseconds_t
Type for durations in milli seconds.
Definition: InfraredTypes.h:29
static const uint32_t INVALID
Definition: LircDevice.h:53
size_t getLength() const
Returns the length of the data.
Definition: IrSequence.h:52
bool isPulse() const
Definition: LircT.h:37
This is the class version of lirc_t, defined in lirc.h.
Definition: LircT.h:9
bool canRecMode2() const
Definition: LircDevice.h:84
microseconds_t getDuration() const
Definition: LircT.h:29
bool canGetRecResolution() const
void report(std::ostream &stream=std::cout) const
Prints a listing of the properties implemented on the stream supplied.
void report(const char *name, bool value, std::ostream &stream) const
Definition: LircDevice.cpp:102
static const bool longReport
Flag indicating how to format reports.
Definition: LircDevice.h:27
void mode2dump(std::ostream &stream=std::cout)
Reads and dumps readings in mode2 format.
milliseconds_t endTimeout
static const microseconds_t replacementEndingSilence
milliseconds_t beginTimeout
Definition: LircDevice.h:35
bool isTerminal() const
Definition: LircT.h:49
This abstract class contains the common functionality of the derived classes.
Definition: LircDevice.h:24
uint32_t microseconds_t
Type for durations in micro seconds.
Definition: InfraredTypes.h:20
int setSendCarrier(int frequency=defaultFrequency)
Set the modulation frequency.
IrSequence * receive()
Reads a sequence.
This class consists of a vector of durations.
Definition: IrSequence.h:15
int write(const uint32_t *data, size_t length)
A low-level interface to the write(2) call on the file descriptor.
int setRecTimeout(int arg)
Set the integer value for IR inactivity timeout (microseconds).
Definition: LircDevice.h:116
bool canSetSendCarrier() const
Mode2LircDevice(const char *path=defaultFilename=defaultFilename, milliseconds_t beginTimeout=defaultBeginTimeout, size_t captureSize=defaultCaptureSize, milliseconds_t endTimeout=defaultEndTimeout)