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