Updated FSF address in all files. Fixes ticket:51
[debian/gnuradio] / ezdop / src / host / hunter / src / serial.cc
1 /*
2  Copyright 2006 Johnathan Corgan.
3  
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License version 2
6  as published by the Free Software Foundation.
7  
8  This software is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with GNU Radio; see the file COPYING.  If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street,
16  Boston, MA 02110-1301, USA.
17 */
18
19 #include "serial.h"
20
21 #include <wx/log.h>
22 #include <errno.h>
23
24 #ifdef __WIN32__
25 // I hate Windows.
26 #else
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/ioctl.h>
30 #endif
31
32 wxArrayString EnumerateSerialPorts()
33 {
34     wxArrayString result;
35     
36 #ifdef __WIN32__
37     wxString port;
38     for (int i = 1; i <= 8; i++) {
39         port.Printf("COM%i", i);
40         result.Add(port);
41     }
42 #else
43     result.Add(_T("/dev/ttyS0"));
44     result.Add(_T("/dev/ttyS1"));
45     result.Add(_T("/dev/ttyS2"));
46     result.Add(_T("/dev/ttyS3"));
47     result.Add(_T("/dev/ttyUSB0"));
48     result.Add(_T("/dev/ttyUSB1"));
49 #endif
50
51     return result;
52 }
53
54 SerialPort::SerialPort(wxString &port)
55 {
56     wxLogDebug(_T("SerialPort::SerialPort(): %s"), port.c_str());
57     m_port = port;
58     m_opened = false;
59 #ifdef __WIN32__
60     m_handle = INVALID_HANDLE_VALUE;
61 #else
62     m_fd = -1;
63 #endif
64 }
65
66 bool SerialPort::Open(int speed)
67 {
68     wxLogDebug(_T("SerialPort::Open: %i baud"), speed);
69     if (m_opened) {
70         wxLogWarning(_T("SerialPort::Open: called on already opened object."));
71         return false;
72     }
73
74 #ifdef __WIN32__
75     m_handle = CreateFile(m_port.c_str(), 
76                           GENERIC_READ | GENERIC_WRITE,
77                           0, 
78                           NULL, 
79                           OPEN_EXISTING, 
80                           0, 
81                           NULL);
82     if (m_handle == INVALID_HANDLE_VALUE) {
83         wxLogError("SerialPort::Open: CreateFile() failed");
84         return false;
85     }
86
87     DCB dcb;
88     if (!GetCommState(m_handle, &dcb)) {
89         wxLogError("SerialPort::Open: GetCommState failed.");
90         CloseHandle(m_handle);
91         return false;
92     }
93
94     dcb.BaudRate = speed;
95     dcb.ByteSize = 8;
96     dcb.StopBits = ONESTOPBIT;
97     dcb.Parity = NOPARITY;
98     dcb.fBinary = TRUE;
99     dcb.fParity = FALSE;
100
101     if (!SetCommState(m_handle, &dcb)) {
102         wxLogError("SerialPort::Open: SetCommState failed.");
103         CloseHandle(m_handle);
104         return false;
105     }
106     
107     COMMTIMEOUTS timeouts;
108     if (!GetCommTimeouts(m_handle, &timeouts)) {
109         wxLogError("SerialPort::Open: GetCommTimeouts failed.");
110         CloseHandle(m_handle);
111         return false;
112     }
113
114     timeouts.ReadIntervalTimeout = MAXDWORD;
115     timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
116     timeouts.ReadTotalTimeoutConstant = 100;
117
118     if (!SetCommTimeouts(m_handle, &timeouts)) {
119         wxLogError("SerialPort::Open: SetCommTimeouts failed.");
120         CloseHandle(m_handle);
121         return false;
122     }
123
124     m_opened = true;
125 #else
126     // Fixed at first USB port until string bug fixed
127     m_fd = open("/dev/ttyUSB0", O_RDWR|O_NONBLOCK);
128     if (m_fd < 0) {
129         wxLogError(_T("SerialPort::Open: open(): %i"), errno);
130         return false;
131     }
132
133     if (!isatty(m_fd)) {
134         wxLogError(_T("SerialPort::Open: device %s is not a tty"), m_port.c_str());
135         close(m_fd);
136         return false;
137     }
138
139     if (tcgetattr(m_fd, &m_ttyset_old) != 0) {
140         wxLogError(_T("SerialPort::Open: failed to get port attributes"));
141         close(m_fd);
142         return false;
143     }
144
145     memcpy(&m_ttyset_new, &m_ttyset_old, sizeof(m_ttyset_new));
146         cfsetispeed(&m_ttyset_new, (speed_t)speed);
147         cfsetospeed(&m_ttyset_new, (speed_t)speed);
148         m_ttyset_new.c_cflag &= ~(PARENB|CRTSCTS); // Disable parity and flowcontrol
149         m_ttyset_new.c_cflag |= CS8|CREAD|CLOCAL;  // 8 bits, read, no modem status lines
150         m_ttyset_new.c_iflag = 0;
151         m_ttyset_new.c_oflag = ONLCR;              // Convert LF to CRLF on receive
152         m_ttyset_new.c_lflag = 0;
153
154         if (tcsetattr(m_fd, TCSANOW, &m_ttyset_new) != 0) {
155         wxLogError(_T("SerialPort::Open: failed to set port attributes"));
156         close(m_fd);
157             return false;
158     }
159
160     m_opened = true;
161 #endif
162     return m_opened;
163 }
164
165 void SerialPort::Close()
166 {
167     wxLogDebug(_T("SerialPort::Close()"));
168 #ifdef __WIN32__
169     CloseHandle(m_handle);
170 #else
171     if (m_opened >= 0) {
172         m_ttyset_old.c_cflag |= HUPCL;
173         tcsetattr(m_fd, TCSANOW, &m_ttyset_old);
174         close(m_fd);
175     }
176 #endif
177
178     m_opened = false;
179 }
180
181 SerialPort::~SerialPort()
182 {
183     wxLogDebug(_T("SerialPort::~SerialPort()"));
184
185     if (m_opened)
186         Close();
187 }
188
189 int SerialPort::RxReady()
190 {
191     int count = 0;
192 #ifdef __WIN32__
193     return 1; // No equivalent Win32 call, use read timeouts instead
194 #else
195     if (m_fd < 0 || ioctl(m_fd, FIONREAD, &count) < 0)
196         return -1;
197 #endif
198     return count;
199 }
200
201 int SerialPort::Read(char *buffer, int len)
202 {
203     wxASSERT(buffer);
204     wxASSERT(len);
205
206     if (!m_opened)
207         return -1;
208         
209 #ifdef __WIN32__
210     DWORD num;
211     if (ReadFile(m_handle, buffer, (DWORD)len, &num, NULL))
212         return num;
213     else
214         return -1;
215 #else
216     return read(m_fd, buffer, len);
217 #endif
218 }