| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/serial/serial_io_handler_posix.h" | 5 #include "device/serial/serial_io_handler_posix.h" |
| 6 | 6 |
| 7 #include <sys/ioctl.h> | 7 #include <sys/ioctl.h> |
| 8 #include <termios.h> | 8 #include <termios.h> |
| 9 | 9 |
| 10 #include "base/posix/eintr_wrapper.h" | 10 #include "base/posix/eintr_wrapper.h" |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 QueueReadCompleted(0, read_cancel_reason()); | 189 QueueReadCompleted(0, read_cancel_reason()); |
| 190 } | 190 } |
| 191 | 191 |
| 192 void SerialIoHandlerPosix::CancelWriteImpl() { | 192 void SerialIoHandlerPosix::CancelWriteImpl() { |
| 193 DCHECK(CalledOnValidThread()); | 193 DCHECK(CalledOnValidThread()); |
| 194 is_watching_writes_ = false; | 194 is_watching_writes_ = false; |
| 195 file_write_watcher_.StopWatchingFileDescriptor(); | 195 file_write_watcher_.StopWatchingFileDescriptor(); |
| 196 QueueWriteCompleted(0, write_cancel_reason()); | 196 QueueWriteCompleted(0, write_cancel_reason()); |
| 197 } | 197 } |
| 198 | 198 |
| 199 bool SerialIoHandlerPosix::ConfigurePortImpl() { |
| 200 struct termios config; |
| 201 if (tcgetattr(file().GetPlatformFile(), &config) != 0) { |
| 202 VPLOG(1) << "Failed to get port attributes"; |
| 203 return false; |
| 204 } |
| 205 |
| 206 // Set flags for 'raw' operation |
| 207 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); |
| 208 config.c_iflag &= |
| 209 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); |
| 210 config.c_oflag &= ~OPOST; |
| 211 |
| 212 // CLOCAL causes the system to disregard the DCD signal state. |
| 213 // CREAD enables reading from the port. |
| 214 config.c_cflag |= (CLOCAL | CREAD); |
| 215 |
| 216 DCHECK(options().bitrate); |
| 217 speed_t bitrate_opt = B0; |
| 218 if (BitrateToSpeedConstant(options().bitrate, &bitrate_opt)) { |
| 219 cfsetispeed(&config, bitrate_opt); |
| 220 cfsetospeed(&config, bitrate_opt); |
| 221 } else { |
| 222 // Attempt to set a custom speed. |
| 223 if (!SetCustomBitrate(file().GetPlatformFile(), &config, |
| 224 options().bitrate)) { |
| 225 return false; |
| 226 } |
| 227 } |
| 228 |
| 229 DCHECK(options().data_bits != serial::DATA_BITS_NONE); |
| 230 config.c_cflag &= ~CSIZE; |
| 231 switch (options().data_bits) { |
| 232 case serial::DATA_BITS_SEVEN: |
| 233 config.c_cflag |= CS7; |
| 234 break; |
| 235 case serial::DATA_BITS_EIGHT: |
| 236 default: |
| 237 config.c_cflag |= CS8; |
| 238 break; |
| 239 } |
| 240 |
| 241 DCHECK(options().parity_bit != serial::PARITY_BIT_NONE); |
| 242 switch (options().parity_bit) { |
| 243 case serial::PARITY_BIT_EVEN: |
| 244 config.c_cflag |= PARENB; |
| 245 config.c_cflag &= ~PARODD; |
| 246 break; |
| 247 case serial::PARITY_BIT_ODD: |
| 248 config.c_cflag |= (PARODD | PARENB); |
| 249 break; |
| 250 case serial::PARITY_BIT_NO: |
| 251 default: |
| 252 config.c_cflag &= ~(PARODD | PARENB); |
| 253 break; |
| 254 } |
| 255 |
| 256 DCHECK(options().stop_bits != serial::STOP_BITS_NONE); |
| 257 switch (options().stop_bits) { |
| 258 case serial::STOP_BITS_TWO: |
| 259 config.c_cflag |= CSTOPB; |
| 260 break; |
| 261 case serial::STOP_BITS_ONE: |
| 262 default: |
| 263 config.c_cflag &= ~CSTOPB; |
| 264 break; |
| 265 } |
| 266 |
| 267 DCHECK(options().has_cts_flow_control); |
| 268 if (options().cts_flow_control) { |
| 269 config.c_cflag |= CRTSCTS; |
| 270 } else { |
| 271 config.c_cflag &= ~CRTSCTS; |
| 272 } |
| 273 |
| 274 if (tcsetattr(file().GetPlatformFile(), TCSANOW, &config) != 0) { |
| 275 VPLOG(1) << "Failed to set port attributes"; |
| 276 return false; |
| 277 } |
| 278 return true; |
| 279 } |
| 280 |
| 199 SerialIoHandlerPosix::SerialIoHandlerPosix( | 281 SerialIoHandlerPosix::SerialIoHandlerPosix( |
| 200 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, | 282 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, |
| 201 scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) | 283 scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) |
| 202 : SerialIoHandler(file_thread_message_loop, ui_thread_message_loop), | 284 : SerialIoHandler(file_thread_message_loop, ui_thread_message_loop), |
| 203 is_watching_reads_(false), | 285 is_watching_reads_(false), |
| 204 is_watching_writes_(false) { | 286 is_watching_writes_(false) { |
| 205 } | 287 } |
| 206 | 288 |
| 207 SerialIoHandlerPosix::~SerialIoHandlerPosix() { | 289 SerialIoHandlerPosix::~SerialIoHandlerPosix() { |
| 208 } | 290 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 is_watching_writes_ = | 357 is_watching_writes_ = |
| 276 base::MessageLoopForIO::current()->WatchFileDescriptor( | 358 base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 277 file().GetPlatformFile(), | 359 file().GetPlatformFile(), |
| 278 true, | 360 true, |
| 279 base::MessageLoopForIO::WATCH_WRITE, | 361 base::MessageLoopForIO::WATCH_WRITE, |
| 280 &file_write_watcher_, | 362 &file_write_watcher_, |
| 281 this); | 363 this); |
| 282 } | 364 } |
| 283 } | 365 } |
| 284 | 366 |
| 285 bool SerialIoHandlerPosix::ConfigurePort( | 367 bool SerialIoHandlerPosix::Flush() const { |
| 286 const serial::ConnectionOptions& options) { | 368 if (tcflush(file().GetPlatformFile(), TCIOFLUSH) != 0) { |
| 287 struct termios config; | 369 VPLOG(1) << "Failed to flush port"; |
| 288 tcgetattr(file().GetPlatformFile(), &config); | 370 return false; |
| 289 if (options.bitrate) { | |
| 290 speed_t bitrate_opt = B0; | |
| 291 if (BitrateToSpeedConstant(options.bitrate, &bitrate_opt)) { | |
| 292 cfsetispeed(&config, bitrate_opt); | |
| 293 cfsetospeed(&config, bitrate_opt); | |
| 294 } else { | |
| 295 // Attempt to set a custom speed. | |
| 296 if (!SetCustomBitrate( | |
| 297 file().GetPlatformFile(), &config, options.bitrate)) { | |
| 298 return false; | |
| 299 } | |
| 300 } | |
| 301 } | 371 } |
| 302 if (options.data_bits != serial::DATA_BITS_NONE) { | 372 return true; |
| 303 config.c_cflag &= ~CSIZE; | |
| 304 switch (options.data_bits) { | |
| 305 case serial::DATA_BITS_SEVEN: | |
| 306 config.c_cflag |= CS7; | |
| 307 break; | |
| 308 case serial::DATA_BITS_EIGHT: | |
| 309 default: | |
| 310 config.c_cflag |= CS8; | |
| 311 break; | |
| 312 } | |
| 313 } | |
| 314 if (options.parity_bit != serial::PARITY_BIT_NONE) { | |
| 315 switch (options.parity_bit) { | |
| 316 case serial::PARITY_BIT_EVEN: | |
| 317 config.c_cflag |= PARENB; | |
| 318 config.c_cflag &= ~PARODD; | |
| 319 break; | |
| 320 case serial::PARITY_BIT_ODD: | |
| 321 config.c_cflag |= (PARODD | PARENB); | |
| 322 break; | |
| 323 case serial::PARITY_BIT_NO: | |
| 324 default: | |
| 325 config.c_cflag &= ~(PARODD | PARENB); | |
| 326 break; | |
| 327 } | |
| 328 } | |
| 329 if (options.stop_bits != serial::STOP_BITS_NONE) { | |
| 330 switch (options.stop_bits) { | |
| 331 case serial::STOP_BITS_TWO: | |
| 332 config.c_cflag |= CSTOPB; | |
| 333 break; | |
| 334 case serial::STOP_BITS_ONE: | |
| 335 default: | |
| 336 config.c_cflag &= ~CSTOPB; | |
| 337 break; | |
| 338 } | |
| 339 } | |
| 340 if (options.has_cts_flow_control) { | |
| 341 if (options.cts_flow_control) { | |
| 342 config.c_cflag |= CRTSCTS; | |
| 343 } else { | |
| 344 config.c_cflag &= ~CRTSCTS; | |
| 345 } | |
| 346 } | |
| 347 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; | |
| 348 } | |
| 349 | |
| 350 bool SerialIoHandlerPosix::PostOpen() { | |
| 351 struct termios config; | |
| 352 tcgetattr(file().GetPlatformFile(), &config); | |
| 353 | |
| 354 // Set flags for 'raw' operation | |
| 355 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); | |
| 356 config.c_iflag &= | |
| 357 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); | |
| 358 config.c_oflag &= ~OPOST; | |
| 359 | |
| 360 // CLOCAL causes the system to disregard the DCD signal state. | |
| 361 // CREAD enables reading from the port. | |
| 362 config.c_cflag |= (CLOCAL | CREAD); | |
| 363 | |
| 364 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; | |
| 365 } | |
| 366 | |
| 367 bool SerialIoHandlerPosix::Flush() const { | |
| 368 return tcflush(file().GetPlatformFile(), TCIOFLUSH) == 0; | |
| 369 } | 373 } |
| 370 | 374 |
| 371 serial::DeviceControlSignalsPtr SerialIoHandlerPosix::GetControlSignals() | 375 serial::DeviceControlSignalsPtr SerialIoHandlerPosix::GetControlSignals() |
| 372 const { | 376 const { |
| 373 int status; | 377 int status; |
| 374 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { | 378 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { |
| 379 VPLOG(1) << "Failed to get port control signals"; |
| 375 return serial::DeviceControlSignalsPtr(); | 380 return serial::DeviceControlSignalsPtr(); |
| 376 } | 381 } |
| 377 | 382 |
| 378 serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New()); | 383 serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New()); |
| 379 signals->dcd = (status & TIOCM_CAR) != 0; | 384 signals->dcd = (status & TIOCM_CAR) != 0; |
| 380 signals->cts = (status & TIOCM_CTS) != 0; | 385 signals->cts = (status & TIOCM_CTS) != 0; |
| 381 signals->dsr = (status & TIOCM_DSR) != 0; | 386 signals->dsr = (status & TIOCM_DSR) != 0; |
| 382 signals->ri = (status & TIOCM_RI) != 0; | 387 signals->ri = (status & TIOCM_RI) != 0; |
| 383 return signals.Pass(); | 388 return signals.Pass(); |
| 384 } | 389 } |
| 385 | 390 |
| 386 bool SerialIoHandlerPosix::SetControlSignals( | 391 bool SerialIoHandlerPosix::SetControlSignals( |
| 387 const serial::HostControlSignals& signals) { | 392 const serial::HostControlSignals& signals) { |
| 388 int status; | 393 int status; |
| 389 | 394 |
| 390 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { | 395 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { |
| 396 VPLOG(1) << "Failed to get port control signals"; |
| 391 return false; | 397 return false; |
| 392 } | 398 } |
| 393 | 399 |
| 394 if (signals.has_dtr) { | 400 if (signals.has_dtr) { |
| 395 if (signals.dtr) { | 401 if (signals.dtr) { |
| 396 status |= TIOCM_DTR; | 402 status |= TIOCM_DTR; |
| 397 } else { | 403 } else { |
| 398 status &= ~TIOCM_DTR; | 404 status &= ~TIOCM_DTR; |
| 399 } | 405 } |
| 400 } | 406 } |
| 401 | 407 |
| 402 if (signals.has_rts) { | 408 if (signals.has_rts) { |
| 403 if (signals.rts) { | 409 if (signals.rts) { |
| 404 status |= TIOCM_RTS; | 410 status |= TIOCM_RTS; |
| 405 } else { | 411 } else { |
| 406 status &= ~TIOCM_RTS; | 412 status &= ~TIOCM_RTS; |
| 407 } | 413 } |
| 408 } | 414 } |
| 409 | 415 |
| 410 return ioctl(file().GetPlatformFile(), TIOCMSET, &status) == 0; | 416 if (ioctl(file().GetPlatformFile(), TIOCMSET, &status) != 0) { |
| 417 VPLOG(1) << "Failed to set port control signals"; |
| 418 return false; |
| 419 } |
| 420 return true; |
| 411 } | 421 } |
| 412 | 422 |
| 413 serial::ConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const { | 423 serial::ConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const { |
| 414 struct termios config; | 424 struct termios config; |
| 415 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { | 425 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { |
| 426 VPLOG(1) << "Failed to get port info"; |
| 416 return serial::ConnectionInfoPtr(); | 427 return serial::ConnectionInfoPtr(); |
| 417 } | 428 } |
| 418 serial::ConnectionInfoPtr info(serial::ConnectionInfo::New()); | 429 serial::ConnectionInfoPtr info(serial::ConnectionInfo::New()); |
| 419 speed_t ispeed = cfgetispeed(&config); | 430 speed_t ispeed = cfgetispeed(&config); |
| 420 speed_t ospeed = cfgetospeed(&config); | 431 speed_t ospeed = cfgetospeed(&config); |
| 421 if (ispeed == ospeed) { | 432 if (ispeed == ospeed) { |
| 422 int bitrate = 0; | 433 int bitrate = 0; |
| 423 if (SpeedConstantToBitrate(ispeed, &bitrate)) { | 434 if (SpeedConstantToBitrate(ispeed, &bitrate)) { |
| 424 info->bitrate = bitrate; | 435 info->bitrate = bitrate; |
| 425 } else if (ispeed > 0) { | 436 } else if (ispeed > 0) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 443 (config.c_cflag & CSTOPB) ? serial::STOP_BITS_TWO : serial::STOP_BITS_ONE; | 454 (config.c_cflag & CSTOPB) ? serial::STOP_BITS_TWO : serial::STOP_BITS_ONE; |
| 444 info->cts_flow_control = (config.c_cflag & CRTSCTS) != 0; | 455 info->cts_flow_control = (config.c_cflag & CRTSCTS) != 0; |
| 445 return info.Pass(); | 456 return info.Pass(); |
| 446 } | 457 } |
| 447 | 458 |
| 448 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 459 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
| 449 return port_name; | 460 return port_name; |
| 450 } | 461 } |
| 451 | 462 |
| 452 } // namespace device | 463 } // namespace device |
| OLD | NEW |