| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/extensions/api/serial/serial_io_handler_posix.h" | 5 #include "chrome/browser/extensions/api/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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) { | 166 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) { |
| 167 DCHECK(CalledOnValidThread()); | 167 DCHECK(CalledOnValidThread()); |
| 168 DCHECK_EQ(fd, file().GetPlatformFile()); | 168 DCHECK_EQ(fd, file().GetPlatformFile()); |
| 169 | 169 |
| 170 if (pending_read_buffer()) { | 170 if (pending_read_buffer()) { |
| 171 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), | 171 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), |
| 172 pending_read_buffer()->data(), | 172 pending_read_buffer()->data(), |
| 173 pending_read_buffer_len())); | 173 pending_read_buffer_len())); |
| 174 if (bytes_read < 0) { | 174 if (bytes_read < 0) { |
| 175 if (errno == ENXIO) { | 175 if (errno == ENXIO) { |
| 176 ReadCompleted(0, api::serial::RECEIVE_ERROR_DEVICE_LOST); | 176 ReadCompleted(0, device::RECEIVE_ERROR_DEVICE_LOST); |
| 177 } else { | 177 } else { |
| 178 ReadCompleted(0, api::serial::RECEIVE_ERROR_SYSTEM_ERROR); | 178 ReadCompleted(0, device::RECEIVE_ERROR_SYSTEM_ERROR); |
| 179 } | 179 } |
| 180 } else if (bytes_read == 0) { | 180 } else if (bytes_read == 0) { |
| 181 ReadCompleted(0, api::serial::RECEIVE_ERROR_DEVICE_LOST); | 181 ReadCompleted(0, device::RECEIVE_ERROR_DEVICE_LOST); |
| 182 } else { | 182 } else { |
| 183 ReadCompleted(bytes_read, api::serial::RECEIVE_ERROR_NONE); | 183 ReadCompleted(bytes_read, device::RECEIVE_ERROR_NONE); |
| 184 } | 184 } |
| 185 } else { | 185 } else { |
| 186 // Stop watching the fd if we get notifications with no pending | 186 // Stop watching the fd if we get notifications with no pending |
| 187 // reads or writes to avoid starving the message loop. | 187 // reads or writes to avoid starving the message loop. |
| 188 is_watching_reads_ = false; | 188 is_watching_reads_ = false; |
| 189 file_read_watcher_.StopWatchingFileDescriptor(); | 189 file_read_watcher_.StopWatchingFileDescriptor(); |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 | 192 |
| 193 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) { | 193 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) { |
| 194 DCHECK(CalledOnValidThread()); | 194 DCHECK(CalledOnValidThread()); |
| 195 DCHECK_EQ(fd, file().GetPlatformFile()); | 195 DCHECK_EQ(fd, file().GetPlatformFile()); |
| 196 | 196 |
| 197 if (pending_write_buffer()) { | 197 if (pending_write_buffer()) { |
| 198 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), | 198 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), |
| 199 pending_write_buffer()->data(), | 199 pending_write_buffer()->data(), |
| 200 pending_write_buffer_len())); | 200 pending_write_buffer_len())); |
| 201 if (bytes_written < 0) { | 201 if (bytes_written < 0) { |
| 202 WriteCompleted(0, api::serial::SEND_ERROR_SYSTEM_ERROR); | 202 WriteCompleted(0, device::SEND_ERROR_SYSTEM_ERROR); |
| 203 } else { | 203 } else { |
| 204 WriteCompleted(bytes_written, api::serial::SEND_ERROR_NONE); | 204 WriteCompleted(bytes_written, device::SEND_ERROR_NONE); |
| 205 } | 205 } |
| 206 } else { | 206 } else { |
| 207 // Stop watching the fd if we get notifications with no pending | 207 // Stop watching the fd if we get notifications with no pending |
| 208 // writes to avoid starving the message loop. | 208 // writes to avoid starving the message loop. |
| 209 is_watching_writes_ = false; | 209 is_watching_writes_ = false; |
| 210 file_write_watcher_.StopWatchingFileDescriptor(); | 210 file_write_watcher_.StopWatchingFileDescriptor(); |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 | 213 |
| 214 void SerialIoHandlerPosix::EnsureWatchingReads() { | 214 void SerialIoHandlerPosix::EnsureWatchingReads() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 232 base::MessageLoopForIO::current()->WatchFileDescriptor( | 232 base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 233 file().GetPlatformFile(), | 233 file().GetPlatformFile(), |
| 234 true, | 234 true, |
| 235 base::MessageLoopForIO::WATCH_WRITE, | 235 base::MessageLoopForIO::WATCH_WRITE, |
| 236 &file_write_watcher_, | 236 &file_write_watcher_, |
| 237 this); | 237 this); |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 | 240 |
| 241 bool SerialIoHandlerPosix::ConfigurePort( | 241 bool SerialIoHandlerPosix::ConfigurePort( |
| 242 const api::serial::ConnectionOptions& options) { | 242 const device::ConnectionOptions& options) { |
| 243 struct termios config; | 243 struct termios config; |
| 244 tcgetattr(file().GetPlatformFile(), &config); | 244 tcgetattr(file().GetPlatformFile(), &config); |
| 245 if (options.bitrate.get()) { | 245 if (options.bitrate) { |
| 246 if (*options.bitrate >= 0) { | 246 speed_t bitrate_opt = B0; |
| 247 speed_t bitrate_opt = B0; | 247 if (BitrateToSpeedConstant(options.bitrate, &bitrate_opt)) { |
| 248 if (BitrateToSpeedConstant(*options.bitrate, &bitrate_opt)) { | 248 cfsetispeed(&config, bitrate_opt); |
| 249 cfsetispeed(&config, bitrate_opt); | 249 cfsetospeed(&config, bitrate_opt); |
| 250 cfsetospeed(&config, bitrate_opt); | 250 } else { |
| 251 } else { | 251 // Attempt to set a custom speed. |
| 252 // Attempt to set a custom speed. | 252 if (!SetCustomBitrate( |
| 253 if (!SetCustomBitrate( | 253 file().GetPlatformFile(), &config, options.bitrate)) { |
| 254 file().GetPlatformFile(), &config, *options.bitrate)) { | 254 return false; |
| 255 return false; | |
| 256 } | |
| 257 } | 255 } |
| 258 } | 256 } |
| 259 } | 257 } |
| 260 if (options.data_bits != api::serial::DATA_BITS_NONE) { | 258 if (options.data_bits != device::DATA_BITS_NONE) { |
| 261 config.c_cflag &= ~CSIZE; | 259 config.c_cflag &= ~CSIZE; |
| 262 switch (options.data_bits) { | 260 switch (options.data_bits) { |
| 263 case api::serial::DATA_BITS_SEVEN: | 261 case device::DATA_BITS_SEVEN: |
| 264 config.c_cflag |= CS7; | 262 config.c_cflag |= CS7; |
| 265 break; | 263 break; |
| 266 case api::serial::DATA_BITS_EIGHT: | 264 case device::DATA_BITS_EIGHT: |
| 267 default: | 265 default: |
| 268 config.c_cflag |= CS8; | 266 config.c_cflag |= CS8; |
| 269 break; | 267 break; |
| 270 } | 268 } |
| 271 } | 269 } |
| 272 if (options.parity_bit != api::serial::PARITY_BIT_NONE) { | 270 if (options.parity_bit != device::PARITY_BIT_NONE) { |
| 273 switch (options.parity_bit) { | 271 switch (options.parity_bit) { |
| 274 case api::serial::PARITY_BIT_EVEN: | 272 case device::PARITY_BIT_EVEN: |
| 275 config.c_cflag |= PARENB; | 273 config.c_cflag |= PARENB; |
| 276 config.c_cflag &= ~PARODD; | 274 config.c_cflag &= ~PARODD; |
| 277 break; | 275 break; |
| 278 case api::serial::PARITY_BIT_ODD: | 276 case device::PARITY_BIT_ODD: |
| 279 config.c_cflag |= (PARODD | PARENB); | 277 config.c_cflag |= (PARODD | PARENB); |
| 280 break; | 278 break; |
| 281 case api::serial::PARITY_BIT_NO: | 279 case device::PARITY_BIT_NO: |
| 282 default: | 280 default: |
| 283 config.c_cflag &= ~(PARODD | PARENB); | 281 config.c_cflag &= ~(PARODD | PARENB); |
| 284 break; | 282 break; |
| 285 } | 283 } |
| 286 } | 284 } |
| 287 if (options.stop_bits != api::serial::STOP_BITS_NONE) { | 285 if (options.stop_bits != device::STOP_BITS_NONE) { |
| 288 switch (options.stop_bits) { | 286 switch (options.stop_bits) { |
| 289 case api::serial::STOP_BITS_TWO: | 287 case device::STOP_BITS_TWO: |
| 290 config.c_cflag |= CSTOPB; | 288 config.c_cflag |= CSTOPB; |
| 291 break; | 289 break; |
| 292 case api::serial::STOP_BITS_ONE: | 290 case device::STOP_BITS_ONE: |
| 293 default: | 291 default: |
| 294 config.c_cflag &= ~CSTOPB; | 292 config.c_cflag &= ~CSTOPB; |
| 295 break; | 293 break; |
| 296 } | 294 } |
| 297 } | 295 } |
| 298 if (options.cts_flow_control.get()) { | 296 if (options.has_cts_flow_control) { |
| 299 if (*options.cts_flow_control) { | 297 if (options.cts_flow_control) { |
| 300 config.c_cflag |= CRTSCTS; | 298 config.c_cflag |= CRTSCTS; |
| 301 } else { | 299 } else { |
| 302 config.c_cflag &= ~CRTSCTS; | 300 config.c_cflag &= ~CRTSCTS; |
| 303 } | 301 } |
| 304 } | 302 } |
| 305 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; | 303 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; |
| 306 } | 304 } |
| 307 | 305 |
| 308 bool SerialIoHandlerPosix::PostOpen() { | 306 bool SerialIoHandlerPosix::PostOpen() { |
| 309 struct termios config; | 307 struct termios config; |
| 310 tcgetattr(file().GetPlatformFile(), &config); | 308 tcgetattr(file().GetPlatformFile(), &config); |
| 311 | 309 |
| 312 // Set flags for 'raw' operation | 310 // Set flags for 'raw' operation |
| 313 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); | 311 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); |
| 314 config.c_iflag &= | 312 config.c_iflag &= |
| 315 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); | 313 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); |
| 316 config.c_oflag &= ~OPOST; | 314 config.c_oflag &= ~OPOST; |
| 317 | 315 |
| 318 // CLOCAL causes the system to disregard the DCD signal state. | 316 // CLOCAL causes the system to disregard the DCD signal state. |
| 319 // CREAD enables reading from the port. | 317 // CREAD enables reading from the port. |
| 320 config.c_cflag |= (CLOCAL | CREAD); | 318 config.c_cflag |= (CLOCAL | CREAD); |
| 321 | 319 |
| 322 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; | 320 return tcsetattr(file().GetPlatformFile(), TCSANOW, &config) == 0; |
| 323 } | 321 } |
| 324 | 322 |
| 325 bool SerialIoHandlerPosix::Flush() const { | 323 bool SerialIoHandlerPosix::Flush() const { |
| 326 return tcflush(file().GetPlatformFile(), TCIOFLUSH) == 0; | 324 return tcflush(file().GetPlatformFile(), TCIOFLUSH) == 0; |
| 327 } | 325 } |
| 328 | 326 |
| 329 bool SerialIoHandlerPosix::GetControlSignals( | 327 device::DeviceControlSignalsPtr SerialIoHandlerPosix::GetControlSignals() |
| 330 api::serial::DeviceControlSignals* signals) const { | 328 const { |
| 331 int status; | 329 int status; |
| 332 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { | 330 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { |
| 333 return false; | 331 return device::DeviceControlSignalsPtr(); |
| 334 } | 332 } |
| 335 | 333 |
| 334 device::DeviceControlSignalsPtr signals(device::DeviceControlSignals::New()); |
| 336 signals->dcd = (status & TIOCM_CAR) != 0; | 335 signals->dcd = (status & TIOCM_CAR) != 0; |
| 337 signals->cts = (status & TIOCM_CTS) != 0; | 336 signals->cts = (status & TIOCM_CTS) != 0; |
| 338 signals->dsr = (status & TIOCM_DSR) != 0; | 337 signals->dsr = (status & TIOCM_DSR) != 0; |
| 339 signals->ri = (status & TIOCM_RI) != 0; | 338 signals->ri = (status & TIOCM_RI) != 0; |
| 340 return true; | 339 return signals.Pass(); |
| 341 } | 340 } |
| 342 | 341 |
| 343 bool SerialIoHandlerPosix::SetControlSignals( | 342 bool SerialIoHandlerPosix::SetControlSignals( |
| 344 const api::serial::HostControlSignals& signals) { | 343 const device::HostControlSignals& signals) { |
| 345 int status; | 344 int status; |
| 346 | 345 |
| 347 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { | 346 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { |
| 348 return false; | 347 return false; |
| 349 } | 348 } |
| 350 | 349 |
| 351 if (signals.dtr.get()) { | 350 if (signals.has_dtr) { |
| 352 if (*signals.dtr) { | 351 if (signals.dtr) { |
| 353 status |= TIOCM_DTR; | 352 status |= TIOCM_DTR; |
| 354 } else { | 353 } else { |
| 355 status &= ~TIOCM_DTR; | 354 status &= ~TIOCM_DTR; |
| 356 } | 355 } |
| 357 } | 356 } |
| 358 | 357 |
| 359 if (signals.rts.get()) { | 358 if (signals.has_rts) { |
| 360 if (*signals.rts) { | 359 if (signals.rts) { |
| 361 status |= TIOCM_RTS; | 360 status |= TIOCM_RTS; |
| 362 } else { | 361 } else { |
| 363 status &= ~TIOCM_RTS; | 362 status &= ~TIOCM_RTS; |
| 364 } | 363 } |
| 365 } | 364 } |
| 366 | 365 |
| 367 return ioctl(file().GetPlatformFile(), TIOCMSET, &status) == 0; | 366 return ioctl(file().GetPlatformFile(), TIOCMSET, &status) == 0; |
| 368 } | 367 } |
| 369 | 368 |
| 370 bool SerialIoHandlerPosix::GetPortInfo( | 369 device::ConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const { |
| 371 api::serial::ConnectionInfo* info) const { | |
| 372 struct termios config; | 370 struct termios config; |
| 373 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { | 371 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { |
| 374 return false; | 372 return device::ConnectionInfoPtr(); |
| 375 } | 373 } |
| 374 device::ConnectionInfoPtr info(device::ConnectionInfo::New()); |
| 376 speed_t ispeed = cfgetispeed(&config); | 375 speed_t ispeed = cfgetispeed(&config); |
| 377 speed_t ospeed = cfgetospeed(&config); | 376 speed_t ospeed = cfgetospeed(&config); |
| 378 if (ispeed == ospeed) { | 377 if (ispeed == ospeed) { |
| 379 int bitrate = 0; | 378 int bitrate = 0; |
| 380 if (SpeedConstantToBitrate(ispeed, &bitrate)) { | 379 if (SpeedConstantToBitrate(ispeed, &bitrate)) { |
| 381 info->bitrate.reset(new int(bitrate)); | 380 info->bitrate = bitrate; |
| 382 } else if (ispeed > 0) { | 381 } else if (ispeed > 0) { |
| 383 info->bitrate.reset(new int(static_cast<int>(ispeed))); | 382 info->bitrate = static_cast<int>(ispeed); |
| 384 } | 383 } |
| 385 } | 384 } |
| 386 if ((config.c_cflag & CSIZE) == CS7) { | 385 if ((config.c_cflag & CSIZE) == CS7) { |
| 387 info->data_bits = api::serial::DATA_BITS_SEVEN; | 386 info->data_bits = device::DATA_BITS_SEVEN; |
| 388 } else if ((config.c_cflag & CSIZE) == CS8) { | 387 } else if ((config.c_cflag & CSIZE) == CS8) { |
| 389 info->data_bits = api::serial::DATA_BITS_EIGHT; | 388 info->data_bits = device::DATA_BITS_EIGHT; |
| 390 } else { | 389 } else { |
| 391 info->data_bits = api::serial::DATA_BITS_NONE; | 390 info->data_bits = device::DATA_BITS_NONE; |
| 392 } | 391 } |
| 393 if (config.c_cflag & PARENB) { | 392 if (config.c_cflag & PARENB) { |
| 394 info->parity_bit = (config.c_cflag & PARODD) ? api::serial::PARITY_BIT_ODD | 393 info->parity_bit = (config.c_cflag & PARODD) ? device::PARITY_BIT_ODD |
| 395 : api::serial::PARITY_BIT_EVEN; | 394 : device::PARITY_BIT_EVEN; |
| 396 } else { | 395 } else { |
| 397 info->parity_bit = api::serial::PARITY_BIT_NO; | 396 info->parity_bit = device::PARITY_BIT_NO; |
| 398 } | 397 } |
| 399 info->stop_bits = (config.c_cflag & CSTOPB) ? api::serial::STOP_BITS_TWO | 398 info->stop_bits = |
| 400 : api::serial::STOP_BITS_ONE; | 399 (config.c_cflag & CSTOPB) ? device::STOP_BITS_TWO : device::STOP_BITS_ONE; |
| 401 info->cts_flow_control.reset(new bool((config.c_cflag & CRTSCTS) != 0)); | 400 info->cts_flow_control = (config.c_cflag & CRTSCTS) != 0; |
| 402 return true; | 401 return info.Pass(); |
| 403 } | 402 } |
| 404 | 403 |
| 405 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 404 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
| 406 return port_name; | 405 return port_name; |
| 407 } | 406 } |
| 408 | 407 |
| 409 } // namespace extensions | 408 } // namespace extensions |
| OLD | NEW |