HaikuDepot: notify work status from main window
[haiku.git] / src / kits / device / SerialPort.cpp
bloba4255569de7fa10f98e5a764ca9dfa436b08ac7d
1 /*
2 * Copyright 2002-2004, Marcus Overhagen, Stefano Ceccherini.
3 * All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
7 #include <Debug.h>
8 #include <Directory.h>
9 #include <Entry.h>
10 #include <List.h>
11 #include <SerialPort.h>
13 #include <new>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <termios.h>
23 /* The directory where the serial driver publishes its devices */
24 #define SERIAL_DIR "/dev/ports"
26 // Scans a directory and adds the entries it founds as strings to the
27 // given list
28 static int32
29 scan_directory(const char *directory, BList *list)
31 BEntry entry;
32 BDirectory dir(SERIAL_DIR);
33 char buf[B_OS_NAME_LENGTH];
35 ASSERT(list != NULL);
36 while (dir.GetNextEntry(&entry) == B_OK) {
37 entry.GetName(buf);
38 list->AddItem(strdup(buf));
41 return list->CountItems();
45 /*! \brief Creates and initializes a BSerialPort object.
47 Query the driver, and builds a list of the available
48 serial ports.
49 The BSerialPort object is initialized to these values:
50 - \c B_19200_BPS
51 - \c B_DATA_BITS_8
52 - \c B_STOP_BIT_1
53 - \c B_NO_PARITY
54 - \c B_HARDWARE_CONTROL
55 - \c B_INFINITE_TIMEOUT
56 - Blocking mode
58 BSerialPort::BSerialPort()
60 ffd(-1),
61 fBaudRate(B_19200_BPS),
62 fDataBits(B_DATA_BITS_8),
63 fStopBits(B_STOP_BIT_1),
64 fParityMode(B_NO_PARITY),
65 fFlow(B_HARDWARE_CONTROL),
66 fTimeout(B_INFINITE_TIMEOUT),
67 fBlocking(true),
68 fDevices(new(std::nothrow) BList)
70 _ScanDevices();
74 /*! \brief Frees the resources associated with the object.
75 Closes the port, if it's open, and deletes the devices list.
76 */
77 BSerialPort::~BSerialPort()
79 if (ffd >= 0)
80 close(ffd);
82 if (fDevices != NULL) {
83 for (int32 count = fDevices->CountItems() - 1; count >= 0; count--)
84 free(fDevices->RemoveItem(count));
85 delete fDevices;
90 /*! \brief Opens a serial port.
91 \param portName A valid port name
92 (i.e."/dev/ports/serial2", "serial2", ...)
93 \return
94 - A positive number if the serialport has been succesfully opened.
95 - An errorcode (negative integer) if not.
97 status_t
98 BSerialPort::Open(const char *portName)
100 char buf[64];
102 if (portName == NULL)
103 return B_BAD_VALUE; // Heheee, we won't crash
105 if (portName[0] != '/')
106 snprintf(buf, 64, SERIAL_DIR"/%s", portName);
107 else
108 // A name like "/dev/ports/serial2" was passed
109 snprintf(buf, 64, "%s", portName);
111 if (ffd >= 0) //If this port is already open, close it
112 close(ffd);
114 // TODO: BeOS don't use O_EXCL, and this seems to lead
115 // to some issues. I added this flag having read some comments
116 // by Marco Nelissen on the annotated BeBook.
117 // I think BeOS uses O_RDWR|O_NONBLOCK here.
118 ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL);
120 if (ffd >= 0) {
121 // we used open() with O_NONBLOCK flag to let it return immediately,
122 // but we want read/write operations to block if needed,
123 // so we clear that bit here.
124 int flags = fcntl(ffd, F_GETFL);
125 fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK);
127 _DriverControl();
129 // TODO: I wonder why the return type is a status_t,
130 // since we (as BeOS does) return the descriptor number for the device...
131 return (ffd >= 0) ? ffd : errno;
135 /*! \brief Closes the port.
137 void
138 BSerialPort::Close(void)
140 if (ffd >= 0)
141 close(ffd);
142 ffd = -1;
146 /*! \brief Reads some bytes from the serial port.
147 \param buf The buffer where to copy the data.
148 \param count The maximum amount of bytes to read.
149 \return The amount of data read.
151 ssize_t
152 BSerialPort::Read(void *buf, size_t count)
154 ssize_t err = read(ffd, buf, count);
156 return (err >= 0) ? err : errno;
160 /*! \brief Writes some bytes to the serial port.
161 \param buf The buffer which copy the data from.
162 \param count The amount of bytes to write.
164 ssize_t
165 BSerialPort::Write(const void *buf, size_t count)
167 ssize_t err = write(ffd, buf, count);
169 return (err >= 0) ? err : errno;
173 /*! \brief Set blocking mode
174 \param Blocking If true, enables the blocking mode. If false, disables it.
176 void
177 BSerialPort::SetBlocking(bool Blocking)
179 fBlocking = Blocking;
180 _DriverControl();
184 /*! \brief Set the timeout for the port.
185 \param microSeconds The timeout for the port.
186 Valid values are:
187 - \c B_INFINITE_TIMEOUT
188 - Any value between 0 and 25,000,000, but remember that the granularity
189 of the serial driver is 100,000 microseconds.
191 status_t
192 BSerialPort::SetTimeout(bigtime_t microSeconds)
194 status_t err = B_BAD_VALUE;
196 if (microSeconds == B_INFINITE_TIMEOUT || microSeconds <= 25000000) {
197 fTimeout = microSeconds;
198 _DriverControl();
199 err = B_OK;
201 return err;
205 /*! \brief Set the Baud rate for the port.
206 \param bitsPerSeconds The baud rate.
207 Valid values:
208 - \c B_0_BPS
209 - \c B_50_BPS
210 - \c B_75_BPS
211 - \c B_110_BPS
212 - \c B_134_BPS
213 - \c B_150_BPS
214 - \c B_200_BPS
215 - \c B_300_BPS
216 - \c B_600_BPS
217 - \c B_1200_BPS
218 - \c B_1800_BPS
219 - \c B_2400_BPS
220 - \c B_4800_BPS
221 - \c B_9600_BPS
222 - \c B_19200_BPS
223 - \c B_38400_BPS
224 - \c B_57600_BPS
225 - \c B_115200_BPS
226 - \c B_230400_BPS
227 - \c B_31250_BPS
228 \return
229 - \c B_OK if all goes fine,
230 - an error code if something goes wrong.
232 status_t
233 BSerialPort::SetDataRate(data_rate bitsPerSecond)
235 fBaudRate = bitsPerSecond;
237 return _DriverControl();
241 /*! \brief Get the current Baud Rate.
242 \return The current Baud Rate.
245 data_rate
246 BSerialPort::DataRate(void)
248 return fBaudRate;
252 /*! \brief Set the data bits (7 or 8)
254 void
255 BSerialPort::SetDataBits(data_bits numBits)
257 fDataBits = numBits;
258 _DriverControl();
262 /*! \brief Get the current data bits.
263 \return The current data bits.
265 data_bits
266 BSerialPort::DataBits(void)
268 return fDataBits;
272 /*! \brief Set the stop bits.
273 \param numBits The number of stop bits
274 Valid values:
275 - \c B_STOP_BITS_1 (or \c B_STOP_BIT_1)
276 - \c B_STOP_BITS_2
278 void
279 BSerialPort::SetStopBits(stop_bits numBits)
281 fStopBits = numBits;
282 _DriverControl();
286 /*! \brief Get the current stop bits.
287 \return The current stop bits.
289 stop_bits
290 BSerialPort::StopBits(void)
292 return fStopBits;
296 /*! \brief Set the parity mode.
297 \param which The parity mode to set.
298 Valid values:
299 - \c B_ODD_PARITY
300 - \c B_EVEN_PARITY
301 - \c B_NO_PARITY
303 void
304 BSerialPort::SetParityMode(parity_mode which)
306 fParityMode = which;
307 _DriverControl();
311 /*! \brief Get the parity mode.
312 \return The current parity mode.
314 parity_mode
315 BSerialPort::ParityMode(void)
317 return fParityMode;
321 /*! \brief Clear the input buffer.
323 void
324 BSerialPort::ClearInput(void)
326 tcflush(ffd, TCIFLUSH);
330 /*! \brief Clear the output buffer.
332 void
333 BSerialPort::ClearOutput(void)
335 tcflush(ffd, TCOFLUSH);
339 /*! \brief Set the flow control
340 \param method The type of flow control.
341 Valid values:
342 - \c B_HARDWARE_CONTROL
343 - \c B_SOFTWARE_CONTROL
344 - \c B_NOFLOW_CONTROL
346 void
347 BSerialPort::SetFlowControl(uint32 method)
349 fFlow = method;
350 _DriverControl();
354 /*! \brief Returns the selected flow control.
355 \return The flow control for the current open port.
357 uint32
358 BSerialPort::FlowControl(void)
360 return fFlow;
364 /* Set the DTR */
365 status_t
366 BSerialPort::SetDTR(bool asserted)
368 status_t status = ioctl(ffd, TCSETDTR, &asserted);
370 return (status >= 0) ? status : errno;
374 /* Set the RTS status */
375 status_t
376 BSerialPort::SetRTS(bool asserted)
378 status_t status = ioctl(ffd, TCSETRTS, &asserted);
380 return (status >= 0) ? status : errno;
384 /*! \brief See how many chars are queued on the serial port.
385 \param numChars A pointer to an int32 where you want
386 that value stored.
387 \return ?
389 status_t
390 BSerialPort::NumCharsAvailable(int32 *numChars)
392 //No help from the BeBook...
393 if (ffd < 0)
394 return B_NO_INIT;
396 // TODO: Implement ?
397 if (numChars)
398 *numChars = 0;
399 return B_OK;
403 /*! \brief See if the Clear to Send pin is asserted.
404 \return true if CTS is asserted, false if not.
406 bool
407 BSerialPort::IsCTS(void)
409 unsigned int bits = ioctl(ffd, TCGETBITS, 0);
411 if (bits & TCGB_CTS)
412 return true;
414 return false;
418 /*! \brief See if the Data Set Ready pin is asserted.
419 \return true if DSR is asserted, false if not.
421 bool
422 BSerialPort::IsDSR(void)
424 unsigned int bits = ioctl(ffd, TCGETBITS, 0);
426 if (bits & TCGB_DSR)
427 return true;
429 return false;
433 /*! \brief See if the Ring Indicator pin is asserted.
434 \return true if RI is asserted, false if not.
436 bool
437 BSerialPort::IsRI(void)
439 unsigned int bits = ioctl(ffd, TCGETBITS, 0);
441 if (bits & TCGB_RI)
442 return true;
444 return false;
448 /*! \brief See if the Data Carrier Detect pin is asserted.
449 \return true if DCD is asserted, false if not.
451 bool
452 BSerialPort::IsDCD(void)
454 unsigned int bits = ioctl(ffd, TCGETBITS, 0);
456 if (bits & TCGB_DCD)
457 return true;
459 return false;
463 /*! \brief Wait until there's something to read from the serial port.
464 If no data is ready, it will always block, ignoring the
465 value of SetBlocking(); however, it respects the timeout
466 set by SetTimeout().
467 \return The number of bytes available to be read.
469 ssize_t
470 BSerialPort::WaitForInput(void)
472 ssize_t size;
473 int err = ioctl(ffd, TCWAITEVENT, &size, sizeof size);
475 return (err < B_OK) ? errno : size;
479 /*! \brief Count the number of available Serial Ports.
480 \return An integer which represents the number of available
481 serial ports.
483 int32
484 BSerialPort::CountDevices()
486 int32 count = 0;
488 // Refresh devices list
489 _ScanDevices();
491 if (fDevices != NULL)
492 count = fDevices->CountItems();
494 return count;
498 /*! \brief Get the device name for the given device.
499 \param n Number of the device you want to know the name of.
500 \param name The buffer where you want to store the name.
501 \param bufSize The size of the buffer.
502 \return
503 - \c B_ERROR if something goes wrong
504 - \c B_OK if all goes fine.
506 status_t
507 BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize)
509 status_t result = B_ERROR;
510 const char *dev = NULL;
512 if (fDevices != NULL)
513 dev = static_cast<char*>(fDevices->ItemAt(n));
515 if (dev != NULL && name != NULL) {
516 strncpy(name, dev, bufSize);
517 name[bufSize - 1] = '\0';
518 result = B_OK;
520 return result;
524 /* Private or Reserved */
526 /*! \brief Build a list of available serial ports.
527 Query the serial driver about the available devices,
528 and build a list of them.
530 void
531 BSerialPort::_ScanDevices()
533 // First, we empty the list
534 if (fDevices != NULL) {
535 for (int32 count = fDevices->CountItems() - 1; count >= 0; count--)
536 free(fDevices->RemoveItem(count));
538 // Add devices to the list
539 scan_directory(SERIAL_DIR, fDevices);
544 /*! \brief Send the selected options to the serial driver.
545 \return
546 - \c B_OK if all goes fine,
547 - an error code if something goes wrong.
550 BSerialPort::_DriverControl()
552 struct termios options;
553 int err;
555 if (ffd < 0)
556 return B_NO_INIT;
558 //Load the current settings
559 err = tcgetattr(ffd, &options);
560 if (err < 0)
561 return errno;
563 // Reset all flags
564 options.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK);
565 options.c_cflag &= ~(CRTSCTS | CSIZE | CSTOPB | PARODD | PARENB);
566 options.c_lflag &= ~(ECHO | ECHONL | ISIG | ICANON);
568 // Local line
569 options.c_cflag |= CLOCAL;
571 //Set the flags to the wanted values
572 if (fFlow & B_HARDWARE_CONTROL)
573 options.c_cflag |= CRTSCTS;
575 if (fFlow & B_SOFTWARE_CONTROL)
576 options.c_iflag |= (IXON | IXOFF);
578 if (fStopBits & B_STOP_BITS_2)
579 options.c_cflag |= CSTOPB; // Set 2 stop bits
581 if (fDataBits & B_DATA_BITS_8)
582 options.c_cflag |= CS8; // Set 8 data bits
584 //Ok, set the parity now
585 if (fParityMode != B_NO_PARITY) {
586 options.c_cflag |= PARENB; //Enable parity
587 if (fParityMode == B_ODD_PARITY)
588 options.c_cflag |= PARODD; //Select odd parity
591 //Set the baud rate
592 cfsetispeed(&options, fBaudRate);
593 cfsetospeed(&options, fBaudRate);
595 //Set the timeout
596 options.c_cc[VTIME] = 0;
597 options.c_cc[VMIN] = 0;
598 if (fBlocking) {
599 if (fTimeout == B_INFINITE_TIMEOUT) {
600 options.c_cc[VMIN] = 1;
601 } else if (fTimeout != 0) {
602 int timeout = fTimeout / 100000;
603 options.c_cc[VTIME] = (timeout == 0) ? 1 : timeout;
607 //Ok, finished. Now tell the driver what we decided
608 err = tcsetattr(ffd, TCSANOW, &options);
610 return (err >= 0) ? err : errno;
614 /* These functions are here to maintain Binary Compatibility */
615 void BSerialPort::_ReservedSerialPort1() {}
616 void BSerialPort::_ReservedSerialPort2() {}
617 void BSerialPort::_ReservedSerialPort3() {}
618 void BSerialPort::_ReservedSerialPort4() {}