2 * Copyright 2002-2004, Marcus Overhagen, Stefano Ceccherini.
4 * Distributed under the terms of the MIT License.
11 #include <SerialPort.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
29 scan_directory(const char *directory
, BList
*list
)
32 BDirectory
dir(SERIAL_DIR
);
33 char buf
[B_OS_NAME_LENGTH
];
36 while (dir
.GetNextEntry(&entry
) == B_OK
) {
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
49 The BSerialPort object is initialized to these values:
54 - \c B_HARDWARE_CONTROL
55 - \c B_INFINITE_TIMEOUT
58 BSerialPort::BSerialPort()
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
),
68 fDevices(new(std::nothrow
) BList
)
74 /*! \brief Frees the resources associated with the object.
75 Closes the port, if it's open, and deletes the devices list.
77 BSerialPort::~BSerialPort()
82 if (fDevices
!= NULL
) {
83 for (int32 count
= fDevices
->CountItems() - 1; count
>= 0; count
--)
84 free(fDevices
->RemoveItem(count
));
90 /*! \brief Opens a serial port.
91 \param portName A valid port name
92 (i.e."/dev/ports/serial2", "serial2", ...)
94 - A positive number if the serialport has been succesfully opened.
95 - An errorcode (negative integer) if not.
98 BSerialPort::Open(const char *portName
)
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
);
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
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
);
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
);
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.
138 BSerialPort::Close(void)
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.
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.
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.
177 BSerialPort::SetBlocking(bool Blocking
)
179 fBlocking
= Blocking
;
184 /*! \brief Set the timeout for the port.
185 \param microSeconds The timeout for the port.
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.
192 BSerialPort::SetTimeout(bigtime_t microSeconds
)
194 status_t err
= B_BAD_VALUE
;
196 if (microSeconds
== B_INFINITE_TIMEOUT
|| microSeconds
<= 25000000) {
197 fTimeout
= microSeconds
;
205 /*! \brief Set the Baud rate for the port.
206 \param bitsPerSeconds The baud rate.
229 - \c B_OK if all goes fine,
230 - an error code if something goes wrong.
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.
246 BSerialPort::DataRate(void)
252 /*! \brief Set the data bits (7 or 8)
255 BSerialPort::SetDataBits(data_bits numBits
)
262 /*! \brief Get the current data bits.
263 \return The current data bits.
266 BSerialPort::DataBits(void)
272 /*! \brief Set the stop bits.
273 \param numBits The number of stop bits
275 - \c B_STOP_BITS_1 (or \c B_STOP_BIT_1)
279 BSerialPort::SetStopBits(stop_bits numBits
)
286 /*! \brief Get the current stop bits.
287 \return The current stop bits.
290 BSerialPort::StopBits(void)
296 /*! \brief Set the parity mode.
297 \param which The parity mode to set.
304 BSerialPort::SetParityMode(parity_mode which
)
311 /*! \brief Get the parity mode.
312 \return The current parity mode.
315 BSerialPort::ParityMode(void)
321 /*! \brief Clear the input buffer.
324 BSerialPort::ClearInput(void)
326 tcflush(ffd
, TCIFLUSH
);
330 /*! \brief Clear the output buffer.
333 BSerialPort::ClearOutput(void)
335 tcflush(ffd
, TCOFLUSH
);
339 /*! \brief Set the flow control
340 \param method The type of flow control.
342 - \c B_HARDWARE_CONTROL
343 - \c B_SOFTWARE_CONTROL
344 - \c B_NOFLOW_CONTROL
347 BSerialPort::SetFlowControl(uint32 method
)
354 /*! \brief Returns the selected flow control.
355 \return The flow control for the current open port.
358 BSerialPort::FlowControl(void)
366 BSerialPort::SetDTR(bool asserted
)
368 status_t status
= ioctl(ffd
, TCSETDTR
, &asserted
);
370 return (status
>= 0) ? status
: errno
;
374 /* Set the RTS status */
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
390 BSerialPort::NumCharsAvailable(int32
*numChars
)
392 //No help from the BeBook...
403 /*! \brief See if the Clear to Send pin is asserted.
404 \return true if CTS is asserted, false if not.
407 BSerialPort::IsCTS(void)
409 unsigned int bits
= ioctl(ffd
, TCGETBITS
, 0);
418 /*! \brief See if the Data Set Ready pin is asserted.
419 \return true if DSR is asserted, false if not.
422 BSerialPort::IsDSR(void)
424 unsigned int bits
= ioctl(ffd
, TCGETBITS
, 0);
433 /*! \brief See if the Ring Indicator pin is asserted.
434 \return true if RI is asserted, false if not.
437 BSerialPort::IsRI(void)
439 unsigned int bits
= ioctl(ffd
, TCGETBITS
, 0);
448 /*! \brief See if the Data Carrier Detect pin is asserted.
449 \return true if DCD is asserted, false if not.
452 BSerialPort::IsDCD(void)
454 unsigned int bits
= ioctl(ffd
, TCGETBITS
, 0);
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
467 \return The number of bytes available to be read.
470 BSerialPort::WaitForInput(void)
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
484 BSerialPort::CountDevices()
488 // Refresh devices list
491 if (fDevices
!= NULL
)
492 count
= fDevices
->CountItems();
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.
503 - \c B_ERROR if something goes wrong
504 - \c B_OK if all goes fine.
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';
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.
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.
546 - \c B_OK if all goes fine,
547 - an error code if something goes wrong.
550 BSerialPort::_DriverControl()
552 struct termios options
;
558 //Load the current settings
559 err
= tcgetattr(ffd
, &options
);
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
);
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
592 cfsetispeed(&options
, fBaudRate
);
593 cfsetospeed(&options
, fBaudRate
);
596 options
.c_cc
[VTIME
] = 0;
597 options
.c_cc
[VMIN
] = 0;
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() {}