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