xref: /haiku/src/kits/device/SerialPort.cpp (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
1 /*
2  * Copyright 2002-2004, Marcus Overhagen, Stefano Ceccherini.
3  * All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include <Debug.h>
8 #include <Directory.h>
9 #include <Entry.h>
10 #include <List.h>
11 #include <SerialPort.h>
12 
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <termios.h>
20 
21 /* The directory where the serial driver publishes its devices */
22 #define SERIAL_DIR "/dev/ports"
23 
24 // Scans a directory and adds the entries it founds as strings to the
25 // given list
26 static int32
27 scan_directory(const char *directory, BList *list)
28 {
29 	BEntry entry;
30 	BDirectory dir(SERIAL_DIR);
31 	char buf[B_OS_NAME_LENGTH];
32 
33 	ASSERT(list != NULL);
34 	while (dir.GetNextEntry(&entry) == B_OK) {
35 		entry.GetName(buf);
36 		list->AddItem(strdup(buf));
37 	};
38 
39 	return list->CountItems();
40 }
41 
42 
43 /*! \brief Creates and initializes a BSerialPort object.
44 
45 	Query the driver, and builds a list of the available
46 	serial ports.
47 	The BSerialPort object is initialized to these values:
48 	- \c B_19200_BPS
49 	- \c B_DATA_BITS_8
50 	- \c B_STOP_BIT_1
51 	- \c B_NO_PARITY
52 	- \c B_HARDWARE_CONTROL
53 	- \c B_INFINITE_TIMEOUT
54 	- Blocking mode
55 */
56 BSerialPort::BSerialPort()
57 	:	ffd(-1),
58 		fBaudRate(B_19200_BPS),
59 		fDataBits(B_DATA_BITS_8),
60 		fStopBits(B_STOP_BIT_1),
61 		fParityMode(B_NO_PARITY),
62 		fFlow(B_HARDWARE_CONTROL),
63 		fTimeout(B_INFINITE_TIMEOUT),
64 		fBlocking(true),
65 		_fDevices(new BList)
66 {
67 	ScanDevices();
68 }
69 
70 
71 /*! \brief Frees the resources associated with the object.
72 	Closes the port, if it's open, and deletes the devices list.
73 */
74 BSerialPort::~BSerialPort()
75 {
76 	if (ffd >= 0)
77 		close(ffd);
78 
79 	for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
80 		free(_fDevices->RemoveItem(count));
81 
82 	delete _fDevices;
83 }
84 
85 
86 /*! \brief Opens a serial port.
87 	\param portName A valid port name
88 		(i.e."/dev/ports/serial2", "serial2", ...)
89 	\return
90 	- A positive number if the serialport has been succesfully opened.
91 	- An errorcode (negative integer) if not.
92 */
93 status_t
94 BSerialPort::Open(const char *portName)
95 {
96 	char buf[64];
97 
98 	if (portName == NULL)
99 		return B_BAD_VALUE; // Heheee, we won't crash
100 
101 	if (portName[0] != '/')
102 		snprintf(buf, 64, SERIAL_DIR"/%s", portName);
103 	else
104 		// A name like "/dev/ports/serial2" was passed
105 		snprintf(buf, 64, "%s", portName);
106 
107 	if (ffd >= 0) //If this port is already open, close it
108 		close(ffd);
109 
110 	// TODO: BeOS don't use O_EXCL, and this seems to lead
111 	// to some issues. I added this flag having read some comments
112 	// by Marco Nelissen on the annotated BeBook.
113 	// I think BeOS uses O_RDWR|O_NONBLOCK here.
114 	ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL);
115 
116 	if (ffd >= 0) {
117 		// we used open() with O_NONBLOCK flag to let it return immediately,
118 		// but we want read/write operations to block if needed,
119 		// so we clear that bit here.
120 		int flags = fcntl(ffd, F_GETFL);
121 		fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK);
122 
123 		DriverControl();
124 	}
125 	// TODO: I wonder why the return type is a status_t,
126 	// since we (as BeOS does) return the descriptor number for the device...
127 	return (ffd >= 0) ? ffd : errno;
128 }
129 
130 
131 /*! \brief Closes the port.
132 */
133 void
134 BSerialPort::Close(void)
135 {
136 	if (ffd >= 0)
137 		close(ffd);
138 	ffd = -1;
139 }
140 
141 
142 /*! \brief Reads some bytes from the serial port.
143 	\param buf The buffer where to copy the data.
144 	\param count The maximum amount of bytes to read.
145 	\return The amount of data read.
146 */
147 ssize_t
148 BSerialPort::Read(void *buf, size_t count)
149 {
150 	ssize_t err = read(ffd, buf, count);
151 
152 	return (err >= 0) ? err : errno;
153 }
154 
155 
156 /*! \brief Writes some bytes to the serial port.
157 	\param buf The buffer which copy the data from.
158 	\param count The amount of bytes to write.
159 */
160 ssize_t
161 BSerialPort::Write(const void *buf, size_t count)
162 {
163 	ssize_t err = write(ffd, buf, count);
164 
165 	return (err >= 0) ? err : errno;
166 }
167 
168 
169 /*! \brief Set blocking mode
170 	\param Blocking If true, enables the blocking mode. If false, disables it.
171 */
172 void
173 BSerialPort::SetBlocking(bool Blocking)
174 {
175 	fBlocking = Blocking;
176 	DriverControl();
177 }
178 
179 
180 /*! \brief Set the timeout for the port.
181 	\param microSeconds The timeout for the port.
182 	Valid values are:
183 	- \c B_INFINITE_TIMEOUT
184 	- Any value between 0 and 25,000,000, but remember that the granularity
185 		of the serial driver is 100,000 microseconds.
186 */
187 status_t
188 BSerialPort::SetTimeout(bigtime_t microSeconds)
189 {
190 	status_t err = B_BAD_VALUE;
191 
192 	if (microSeconds == B_INFINITE_TIMEOUT || microSeconds <= 25000000) {
193 		fTimeout = microSeconds;
194 		DriverControl();
195 		err = B_OK;
196 	}
197 	return err;
198 }
199 
200 
201 /*! \brief Set the Baud rate for the port.
202 	\param bitsPerSeconds The baud rate.
203 	Valid values:
204 	- \c B_0_BPS
205 	- \c B_50_BPS
206 	- \c B_75_BPS
207 	- \c B_110_BPS
208 	- \c B_134_BPS
209 	- \c B_150_BPS
210 	- \c B_200_BPS
211 	- \c B_300_BPS
212 	- \c B_600_BPS
213 	- \c B_1200_BPS
214 	- \c B_1800_BPS
215 	- \c B_2400_BPS
216 	- \c B_4800_BPS
217 	- \c B_9600_BPS
218 	- \c B_19200_BPS
219 	- \c B_38400_BPS
220 	- \c B_57600_BPS
221 	- \c B_115200_BPS
222 	- \c B_230400_BPS
223 	- \c B_31250_BPS
224 	\return
225 	- \c B_OK if all goes fine,
226 	- an error code if something goes wrong.
227 */
228 status_t
229 BSerialPort::SetDataRate(data_rate bitsPerSecond)
230 {
231 	fBaudRate = bitsPerSecond;
232 
233 	return DriverControl();
234 }
235 
236 
237 /*! \brief Get the current Baud Rate.
238 	\return The current Baud Rate.
239 */
240 
241 data_rate
242 BSerialPort::DataRate(void)
243 {
244 	return fBaudRate;
245 }
246 
247 
248 /*! \brief Set the data bits (7 or 8)
249 */
250 void
251 BSerialPort::SetDataBits(data_bits numBits)
252 {
253 	fDataBits = numBits;
254 	DriverControl();
255 }
256 
257 
258 /*! \brief Get the current data bits.
259  	\return The current data bits.
260 */
261 data_bits
262 BSerialPort::DataBits(void)
263 {
264 	return fDataBits;
265 }
266 
267 
268 /*! \brief Set the stop bits.
269 	\param numBits The number of stop bits
270 	Valid values:
271 	- \c B_STOP_BITS_1 (or \c B_STOP_BIT_1)
272 	- \c B_STOP_BITS_2
273 */
274 void
275 BSerialPort::SetStopBits(stop_bits numBits)
276 {
277 	fStopBits = numBits;
278 	DriverControl();
279 }
280 
281 
282 /*! \brief Get the current stop bits.
283 	\return The current stop bits.
284 */
285 stop_bits
286 BSerialPort::StopBits(void)
287 {
288 	return fStopBits;
289 }
290 
291 
292 /*! \brief Set the parity mode.
293 	\param which The parity mode to set.
294 	Valid values:
295 	- \c B_ODD_PARITY
296 	- \c B_EVEN_PARITY
297 	- \c B_NO_PARITY
298 */
299 void
300 BSerialPort::SetParityMode(parity_mode which)
301 {
302 	fParityMode = which;
303 	DriverControl();
304 }
305 
306 
307 /*! \brief Get the parity mode.
308 	\return The current parity mode.
309 */
310 parity_mode
311 BSerialPort::ParityMode(void)
312 {
313 	return fParityMode;
314 }
315 
316 
317 /*! \brief Clear the input buffer.
318 */
319 void
320 BSerialPort::ClearInput(void)
321 {
322 	tcflush(ffd, TCIFLUSH);
323 }
324 
325 
326 /*! \brief Clear the output buffer.
327 */
328 void
329 BSerialPort::ClearOutput(void)
330 {
331 	tcflush(ffd, TCOFLUSH);
332 }
333 
334 
335 /*! \brief Set the flow control
336 	\param method The type of flow control.
337 	Valid values:
338 	- \c B_HARDWARE_CONTROL
339 	- \c B_SOFTWARE_CONTROL
340 	- \c B_NOFLOW_CONTROL
341 */
342 void
343 BSerialPort::SetFlowControl(uint32 method)
344 {
345 	fFlow = method;
346 	DriverControl();
347 }
348 
349 
350 /*! \brief Returns the selected flow control.
351 	\return The flow control for the current open port.
352 */
353 uint32
354 BSerialPort::FlowControl(void)
355 {
356 	return fFlow;
357 }
358 
359 
360 /* Set the DTR */
361 status_t
362 BSerialPort::SetDTR(bool asserted)
363 {
364 	status_t status = ioctl(ffd, TCSETDTR, &asserted);
365 
366 	return (status >= 0) ? status : errno;
367 }
368 
369 
370 /* Set the RTS status */
371 status_t
372 BSerialPort::SetRTS(bool asserted)
373 {
374 	status_t status = ioctl(ffd, TCSETRTS, &asserted);
375 
376 	return (status >= 0) ? status : errno;
377 }
378 
379 
380 /*! \brief See how many chars are queued on the serial port.
381 	\param numChars A pointer to an int32 where you want
382 		that value stored.
383 	\return ?
384 */
385 status_t
386 BSerialPort::NumCharsAvailable(int32 *numChars)
387 {
388 	//No help from the BeBook...
389 	if (ffd < 0)
390 		return B_NO_INIT;
391 
392 	// TODO: Implement ?
393 	if (numChars)
394 		*numChars = 0;
395 	return B_OK;
396 }
397 
398 
399 /*! \brief See if the Clear to Send pin is asserted.
400 	\return true if CTS is asserted, false if not.
401 */
402 bool
403 BSerialPort::IsCTS(void)
404 {
405 	unsigned int bits = ioctl(ffd, TCGETBITS, 0);
406 
407 	if (bits & TCGB_CTS)
408 		return true;
409 
410 	return false;
411 }
412 
413 
414 /*! \brief See if the Data Set Ready pin is asserted.
415 	\return true if DSR is asserted, false if not.
416 */
417 bool
418 BSerialPort::IsDSR(void)
419 {
420 	unsigned int bits = ioctl(ffd, TCGETBITS, 0);
421 
422 	if (bits & TCGB_DSR)
423 		return true;
424 
425 	return false;
426 }
427 
428 
429 /*! \brief See if the Ring Indicator pin is asserted.
430 	\return true if RI is asserted, false if not.
431 */
432 bool
433 BSerialPort::IsRI(void)
434 {
435 	unsigned int bits = ioctl(ffd, TCGETBITS, 0);
436 
437 	if (bits & TCGB_RI)
438 		return true;
439 
440 	return false;
441 }
442 
443 
444 /*! \brief See if the Data Carrier Detect pin is asserted.
445 	\return true if DCD is asserted, false if not.
446 */
447 bool
448 BSerialPort::IsDCD(void)
449 {
450 	unsigned int bits = ioctl(ffd, TCGETBITS, 0);
451 
452 	if (bits & TCGB_DCD)
453 		return true;
454 
455 	return false;
456 }
457 
458 
459 /*! \brief Wait until there's something to read from the serial port.
460 	If no data is ready, it will always block, ignoring the
461 	value of SetBlocking(); however, it respects the timeout
462 	set by SetTimeout().
463 	\return The number of bytes available to be read.
464 */
465 ssize_t
466 BSerialPort::WaitForInput(void)
467 {
468 	ssize_t size;
469 	int err = ioctl(ffd, TCWAITEVENT, &size, sizeof size);
470 
471 	return (err < B_OK) ? errno : size;
472 }
473 
474 
475 /*! \brief Count the number of available Serial Ports.
476 	\return An integer which represents the number of available
477 		serial ports.
478 */
479 int32
480 BSerialPort::CountDevices()
481 {
482 	int32 count = 0;
483 
484 	// Refresh devices list
485 	ScanDevices();
486 
487 	if (_fDevices != NULL)
488 		count = _fDevices->CountItems();
489 
490 	return count;
491 }
492 
493 
494 /*! \brief Get the device name for the given device.
495 	\param n Number of the device you want to know the name of.
496 	\param name The buffer where you want to store the name.
497 	\param bufSize The size of the buffer.
498 	\return
499 	- \c B_ERROR if something goes wrong
500 	- \c B_OK if all goes fine.
501 */
502 status_t
503 BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize)
504 {
505 	status_t result = B_ERROR;
506 	const char *dev = NULL;
507 
508 	if (_fDevices != NULL)
509 		dev = static_cast<char*>(_fDevices->ItemAt(n));
510 
511 	if (dev != NULL && name != NULL) {
512 		strncpy(name, dev, bufSize);
513 		name[bufSize - 1] = '\0';
514 		result = B_OK;
515 	}
516 	return result;
517 }
518 
519 
520 /* Private or Reserved */
521 
522 /*! \brief Build a list of available serial ports.
523 	Query the serial driver about the available devices,
524 	and build a list of them.
525 */
526 void
527 BSerialPort::ScanDevices()
528 {
529 	// First, we empty the list
530 	for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
531 		free(_fDevices->RemoveItem(count));
532 
533 	// Add devices to the list
534 	scan_directory(SERIAL_DIR, _fDevices);
535 }
536 
537 
538 /*! \brief Send the selected options to the serial driver.
539 	\return
540 	- \c B_OK if all goes fine,
541 	- an error code if something goes wrong.
542 */
543 int
544 BSerialPort::DriverControl()
545 {
546 	struct termios options;
547 	int err;
548 
549 	if (ffd < 0)
550 		return B_NO_INIT;
551 
552 	//Load the current settings
553 	err = tcgetattr(ffd, &options);
554 	if (err < 0)
555 		return errno;
556 
557 	// Reset all flags
558 	options.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK);
559 	options.c_cflag &= ~(CRTSCTS | CSIZE | CBAUD | CSTOPB | PARODD | PARENB);
560 	options.c_lflag &= ~(ECHO | ECHONL | ISIG | ICANON);
561 
562 	// Local line
563 	options.c_cflag |= CLOCAL;
564 
565 	//Set the flags to the wanted values
566 	if (fFlow & B_HARDWARE_CONTROL)
567 		options.c_cflag |= CRTSCTS;
568 
569 	if (fFlow & B_SOFTWARE_CONTROL)
570 		options.c_iflag |= (IXON | IXOFF);
571 
572 	if (fStopBits & B_STOP_BITS_2)
573 		options.c_cflag |= CSTOPB; // Set 2 stop bits
574 
575 	if (fDataBits & B_DATA_BITS_8)
576 		options.c_cflag |= CS8; // Set 8 data bits
577 
578 	//Ok, set the parity now
579 	if (fParityMode != B_NO_PARITY) {
580 		options.c_cflag |= PARENB; //Enable parity
581 		if (fParityMode == B_ODD_PARITY)
582 			options.c_cflag |= PARODD; //Select odd parity
583 	}
584 
585 	//Set the baud rate
586 	options.c_cflag |= (fBaudRate & CBAUD);
587 
588 	//Set the timeout
589 	options.c_cc[VTIME] = 0;
590 	options.c_cc[VMIN] = 0;
591 	if (fBlocking) {
592 		if (fTimeout == B_INFINITE_TIMEOUT) {
593 			options.c_cc[VMIN] = 1;
594 		} else if (fTimeout != 0) {
595 			int timeout = fTimeout / 100000;
596 			options.c_cc[VTIME] = (timeout == 0) ? 1 : timeout;
597 		}
598 	}
599 
600 	//Ok, finished. Now tell the driver what we decided
601 	err = tcsetattr(ffd, TCSANOW, &options);
602 
603 	return (err >= 0) ? err : errno;
604 }
605 
606 
607 /* These functions are here to maintain Binary Compatibility */
608 void BSerialPort::_ReservedSerialPort1() {}
609 void BSerialPort::_ReservedSerialPort2() {}
610 void BSerialPort::_ReservedSerialPort3() {}
611 void BSerialPort::_ReservedSerialPort4() {}
612