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 <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> 21 22 23 /* The directory where the serial driver publishes its devices */ 24 #define SERIAL_DIR "/dev/ports" 25 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) 30 { 31 BEntry entry; 32 BDirectory dir(SERIAL_DIR); 33 char buf[B_OS_NAME_LENGTH]; 34 35 ASSERT(list != NULL); 36 while (dir.GetNextEntry(&entry) == B_OK) { 37 entry.GetName(buf); 38 list->AddItem(strdup(buf)); 39 }; 40 41 return list->CountItems(); 42 } 43 44 45 /*! \brief Creates and initializes a BSerialPort object. 46 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 57 */ 58 BSerialPort::BSerialPort() 59 : 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) 69 { 70 _ScanDevices(); 71 } 72 73 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() 78 { 79 if (ffd >= 0) 80 close(ffd); 81 82 if (fDevices != NULL) { 83 for (int32 count = fDevices->CountItems() - 1; count >= 0; count--) 84 free(fDevices->RemoveItem(count)); 85 delete fDevices; 86 } 87 } 88 89 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. 96 */ 97 status_t 98 BSerialPort::Open(const char *portName) 99 { 100 char buf[64]; 101 102 if (portName == NULL) 103 return B_BAD_VALUE; // Heheee, we won't crash 104 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); 110 111 if (ffd >= 0) //If this port is already open, close it 112 close(ffd); 113 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); 119 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); 126 127 _DriverControl(); 128 } 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; 132 } 133 134 135 /*! \brief Closes the port. 136 */ 137 void 138 BSerialPort::Close(void) 139 { 140 if (ffd >= 0) 141 close(ffd); 142 ffd = -1; 143 } 144 145 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. 150 */ 151 ssize_t 152 BSerialPort::Read(void *buf, size_t count) 153 { 154 ssize_t err = read(ffd, buf, count); 155 156 return (err >= 0) ? err : errno; 157 } 158 159 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. 163 */ 164 ssize_t 165 BSerialPort::Write(const void *buf, size_t count) 166 { 167 ssize_t err = write(ffd, buf, count); 168 169 return (err >= 0) ? err : errno; 170 } 171 172 173 /*! \brief Set blocking mode 174 \param Blocking If true, enables the blocking mode. If false, disables it. 175 */ 176 void 177 BSerialPort::SetBlocking(bool Blocking) 178 { 179 fBlocking = Blocking; 180 _DriverControl(); 181 } 182 183 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. 190 */ 191 status_t 192 BSerialPort::SetTimeout(bigtime_t microSeconds) 193 { 194 status_t err = B_BAD_VALUE; 195 196 if (microSeconds == B_INFINITE_TIMEOUT || microSeconds <= 25000000) { 197 fTimeout = microSeconds; 198 _DriverControl(); 199 err = B_OK; 200 } 201 return err; 202 } 203 204 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. 231 */ 232 status_t 233 BSerialPort::SetDataRate(data_rate bitsPerSecond) 234 { 235 fBaudRate = bitsPerSecond; 236 237 return _DriverControl(); 238 } 239 240 241 /*! \brief Get the current Baud Rate. 242 \return The current Baud Rate. 243 */ 244 245 data_rate 246 BSerialPort::DataRate(void) 247 { 248 return fBaudRate; 249 } 250 251 252 /*! \brief Set the data bits (7 or 8) 253 */ 254 void 255 BSerialPort::SetDataBits(data_bits numBits) 256 { 257 fDataBits = numBits; 258 _DriverControl(); 259 } 260 261 262 /*! \brief Get the current data bits. 263 \return The current data bits. 264 */ 265 data_bits 266 BSerialPort::DataBits(void) 267 { 268 return fDataBits; 269 } 270 271 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 277 */ 278 void 279 BSerialPort::SetStopBits(stop_bits numBits) 280 { 281 fStopBits = numBits; 282 _DriverControl(); 283 } 284 285 286 /*! \brief Get the current stop bits. 287 \return The current stop bits. 288 */ 289 stop_bits 290 BSerialPort::StopBits(void) 291 { 292 return fStopBits; 293 } 294 295 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 302 */ 303 void 304 BSerialPort::SetParityMode(parity_mode which) 305 { 306 fParityMode = which; 307 _DriverControl(); 308 } 309 310 311 /*! \brief Get the parity mode. 312 \return The current parity mode. 313 */ 314 parity_mode 315 BSerialPort::ParityMode(void) 316 { 317 return fParityMode; 318 } 319 320 321 /*! \brief Clear the input buffer. 322 */ 323 void 324 BSerialPort::ClearInput(void) 325 { 326 tcflush(ffd, TCIFLUSH); 327 } 328 329 330 /*! \brief Clear the output buffer. 331 */ 332 void 333 BSerialPort::ClearOutput(void) 334 { 335 tcflush(ffd, TCOFLUSH); 336 } 337 338 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 345 */ 346 void 347 BSerialPort::SetFlowControl(uint32 method) 348 { 349 fFlow = method; 350 _DriverControl(); 351 } 352 353 354 /*! \brief Returns the selected flow control. 355 \return The flow control for the current open port. 356 */ 357 uint32 358 BSerialPort::FlowControl(void) 359 { 360 return fFlow; 361 } 362 363 364 /* Set the DTR */ 365 status_t 366 BSerialPort::SetDTR(bool asserted) 367 { 368 status_t status = ioctl(ffd, TCSETDTR, &asserted, sizeof(asserted)); 369 370 return (status >= 0) ? status : errno; 371 } 372 373 374 /* Set the RTS status */ 375 status_t 376 BSerialPort::SetRTS(bool asserted) 377 { 378 status_t status = ioctl(ffd, TCSETRTS, &asserted, sizeof(asserted)); 379 380 return (status >= 0) ? status : errno; 381 } 382 383 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 ? 388 */ 389 status_t 390 BSerialPort::NumCharsAvailable(int32 *numChars) 391 { 392 //No help from the BeBook... 393 if (ffd < 0) 394 return B_NO_INIT; 395 396 // TODO: Implement ? 397 if (numChars) 398 *numChars = 0; 399 return B_OK; 400 } 401 402 403 /*! \brief See if the Clear to Send pin is asserted. 404 \return true if CTS is asserted, false if not. 405 */ 406 bool 407 BSerialPort::IsCTS(void) 408 { 409 unsigned int bits = ioctl(ffd, TCGETBITS, 0); 410 411 if (bits & TCGB_CTS) 412 return true; 413 414 return false; 415 } 416 417 418 /*! \brief See if the Data Set Ready pin is asserted. 419 \return true if DSR is asserted, false if not. 420 */ 421 bool 422 BSerialPort::IsDSR(void) 423 { 424 unsigned int bits = ioctl(ffd, TCGETBITS, 0); 425 426 if (bits & TCGB_DSR) 427 return true; 428 429 return false; 430 } 431 432 433 /*! \brief See if the Ring Indicator pin is asserted. 434 \return true if RI is asserted, false if not. 435 */ 436 bool 437 BSerialPort::IsRI(void) 438 { 439 unsigned int bits = ioctl(ffd, TCGETBITS, 0); 440 441 if (bits & TCGB_RI) 442 return true; 443 444 return false; 445 } 446 447 448 /*! \brief See if the Data Carrier Detect pin is asserted. 449 \return true if DCD is asserted, false if not. 450 */ 451 bool 452 BSerialPort::IsDCD(void) 453 { 454 unsigned int bits = ioctl(ffd, TCGETBITS, 0); 455 456 if (bits & TCGB_DCD) 457 return true; 458 459 return false; 460 } 461 462 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. 468 */ 469 ssize_t 470 BSerialPort::WaitForInput(void) 471 { 472 ssize_t size; 473 int err = ioctl(ffd, TCWAITEVENT, &size, sizeof size); 474 475 return (err < B_OK) ? errno : size; 476 } 477 478 479 /*! \brief Count the number of available Serial Ports. 480 \return An integer which represents the number of available 481 serial ports. 482 */ 483 int32 484 BSerialPort::CountDevices() 485 { 486 int32 count = 0; 487 488 // Refresh devices list 489 _ScanDevices(); 490 491 if (fDevices != NULL) 492 count = fDevices->CountItems(); 493 494 return count; 495 } 496 497 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. 505 */ 506 status_t 507 BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize) 508 { 509 status_t result = B_ERROR; 510 const char *dev = NULL; 511 512 if (fDevices != NULL) 513 dev = static_cast<char*>(fDevices->ItemAt(n)); 514 515 if (dev != NULL && name != NULL) { 516 strncpy(name, dev, bufSize); 517 name[bufSize - 1] = '\0'; 518 result = B_OK; 519 } 520 return result; 521 } 522 523 524 /* Private or Reserved */ 525 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. 529 */ 530 void 531 BSerialPort::_ScanDevices() 532 { 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)); 537 538 // Add devices to the list 539 scan_directory(SERIAL_DIR, fDevices); 540 } 541 } 542 543 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. 548 */ 549 int 550 BSerialPort::_DriverControl() 551 { 552 struct termios options; 553 int err; 554 555 if (ffd < 0) 556 return B_NO_INIT; 557 558 //Load the current settings 559 err = tcgetattr(ffd, &options); 560 if (err < 0) 561 return errno; 562 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); 567 568 // Local line 569 options.c_cflag |= CLOCAL; 570 571 //Set the flags to the wanted values 572 if (fFlow & B_HARDWARE_CONTROL) 573 options.c_cflag |= CRTSCTS; 574 575 if (fFlow & B_SOFTWARE_CONTROL) 576 options.c_iflag |= (IXON | IXOFF); 577 578 if (fStopBits & B_STOP_BITS_2) 579 options.c_cflag |= CSTOPB; // Set 2 stop bits 580 581 if (fDataBits & B_DATA_BITS_8) 582 options.c_cflag |= CS8; // Set 8 data bits 583 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 589 } 590 591 //Set the baud rate 592 cfsetispeed(&options, fBaudRate); 593 cfsetospeed(&options, fBaudRate); 594 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; 604 } 605 } 606 607 //Ok, finished. Now tell the driver what we decided 608 err = tcsetattr(ffd, TCSANOW, &options); 609 610 return (err >= 0) ? err : errno; 611 } 612 613 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() {} 619