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