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