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