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::serial::RECEIVE_ERROR_DEVICE_LOST); |
177 } else { | 177 } else { |
178 ReadCompleted(0, api::serial::RECEIVE_ERROR_SYSTEM_ERROR); | 178 ReadCompleted(0, device::serial::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::serial::RECEIVE_ERROR_DEVICE_LOST); |
182 } else { | 182 } else { |
183 ReadCompleted(bytes_read, api::serial::RECEIVE_ERROR_NONE); | 183 ReadCompleted(bytes_read, device::serial::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::serial::SEND_ERROR_SYSTEM_ERROR); |
203 } else { | 203 } else { |
204 WriteCompleted(bytes_written, api::serial::SEND_ERROR_NONE); | 204 WriteCompleted(bytes_written, device::serial::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::serial::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::serial::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::serial::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::serial::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::serial::PARITY_BIT_NONE) { |
273 switch (options.parity_bit) { | 271 switch (options.parity_bit) { |
274 case api::serial::PARITY_BIT_EVEN: | 272 case device::serial::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::serial::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::serial::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::serial::STOP_BITS_NONE) { |
288 switch (options.stop_bits) { | 286 switch (options.stop_bits) { |
289 case api::serial::STOP_BITS_TWO: | 287 case device::serial::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::serial::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::serial::DeviceControlSignalsPtr |
330 api::serial::DeviceControlSignals* signals) const { | 328 SerialIoHandlerPosix::GetControlSignals() 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::serial::DeviceControlSignalsPtr(); |
334 } | 332 } |
335 | 333 |
| 334 device::serial::DeviceControlSignalsPtr signals( |
| 335 device::serial::DeviceControlSignals::New()); |
336 signals->dcd = (status & TIOCM_CAR) != 0; | 336 signals->dcd = (status & TIOCM_CAR) != 0; |
337 signals->cts = (status & TIOCM_CTS) != 0; | 337 signals->cts = (status & TIOCM_CTS) != 0; |
338 signals->dsr = (status & TIOCM_DSR) != 0; | 338 signals->dsr = (status & TIOCM_DSR) != 0; |
339 signals->ri = (status & TIOCM_RI) != 0; | 339 signals->ri = (status & TIOCM_RI) != 0; |
340 return true; | 340 return signals.Pass(); |
341 } | 341 } |
342 | 342 |
343 bool SerialIoHandlerPosix::SetControlSignals( | 343 bool SerialIoHandlerPosix::SetControlSignals( |
344 const api::serial::HostControlSignals& signals) { | 344 const device::serial::HostControlSignals& signals) { |
345 int status; | 345 int status; |
346 | 346 |
347 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { | 347 if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) { |
348 return false; | 348 return false; |
349 } | 349 } |
350 | 350 |
351 if (signals.dtr.get()) { | 351 if (signals.has_dtr) { |
352 if (*signals.dtr) { | 352 if (signals.dtr) { |
353 status |= TIOCM_DTR; | 353 status |= TIOCM_DTR; |
354 } else { | 354 } else { |
355 status &= ~TIOCM_DTR; | 355 status &= ~TIOCM_DTR; |
356 } | 356 } |
357 } | 357 } |
358 | 358 |
359 if (signals.rts.get()) { | 359 if (signals.has_rts) { |
360 if (*signals.rts) { | 360 if (signals.rts) { |
361 status |= TIOCM_RTS; | 361 status |= TIOCM_RTS; |
362 } else { | 362 } else { |
363 status &= ~TIOCM_RTS; | 363 status &= ~TIOCM_RTS; |
364 } | 364 } |
365 } | 365 } |
366 | 366 |
367 return ioctl(file().GetPlatformFile(), TIOCMSET, &status) == 0; | 367 return ioctl(file().GetPlatformFile(), TIOCMSET, &status) == 0; |
368 } | 368 } |
369 | 369 |
370 bool SerialIoHandlerPosix::GetPortInfo( | 370 device::serial::ConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const { |
371 api::serial::ConnectionInfo* info) const { | |
372 struct termios config; | 371 struct termios config; |
373 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { | 372 if (tcgetattr(file().GetPlatformFile(), &config) == -1) { |
374 return false; | 373 return device::serial::ConnectionInfoPtr(); |
375 } | 374 } |
| 375 device::serial::ConnectionInfoPtr info(device::serial::ConnectionInfo::New()); |
376 speed_t ispeed = cfgetispeed(&config); | 376 speed_t ispeed = cfgetispeed(&config); |
377 speed_t ospeed = cfgetospeed(&config); | 377 speed_t ospeed = cfgetospeed(&config); |
378 if (ispeed == ospeed) { | 378 if (ispeed == ospeed) { |
379 int bitrate = 0; | 379 int bitrate = 0; |
380 if (SpeedConstantToBitrate(ispeed, &bitrate)) { | 380 if (SpeedConstantToBitrate(ispeed, &bitrate)) { |
381 info->bitrate.reset(new int(bitrate)); | 381 info->bitrate = bitrate; |
382 } else if (ispeed > 0) { | 382 } else if (ispeed > 0) { |
383 info->bitrate.reset(new int(static_cast<int>(ispeed))); | 383 info->bitrate = static_cast<int>(ispeed); |
384 } | 384 } |
385 } | 385 } |
386 if ((config.c_cflag & CSIZE) == CS7) { | 386 if ((config.c_cflag & CSIZE) == CS7) { |
387 info->data_bits = api::serial::DATA_BITS_SEVEN; | 387 info->data_bits = device::serial::DATA_BITS_SEVEN; |
388 } else if ((config.c_cflag & CSIZE) == CS8) { | 388 } else if ((config.c_cflag & CSIZE) == CS8) { |
389 info->data_bits = api::serial::DATA_BITS_EIGHT; | 389 info->data_bits = device::serial::DATA_BITS_EIGHT; |
390 } else { | 390 } else { |
391 info->data_bits = api::serial::DATA_BITS_NONE; | 391 info->data_bits = device::serial::DATA_BITS_NONE; |
392 } | 392 } |
393 if (config.c_cflag & PARENB) { | 393 if (config.c_cflag & PARENB) { |
394 info->parity_bit = (config.c_cflag & PARODD) ? api::serial::PARITY_BIT_ODD | 394 info->parity_bit = (config.c_cflag & PARODD) |
395 : api::serial::PARITY_BIT_EVEN; | 395 ? device::serial::PARITY_BIT_ODD |
| 396 : device::serial::PARITY_BIT_EVEN; |
396 } else { | 397 } else { |
397 info->parity_bit = api::serial::PARITY_BIT_NO; | 398 info->parity_bit = device::serial::PARITY_BIT_NO; |
398 } | 399 } |
399 info->stop_bits = (config.c_cflag & CSTOPB) ? api::serial::STOP_BITS_TWO | 400 info->stop_bits = (config.c_cflag & CSTOPB) ? device::serial::STOP_BITS_TWO |
400 : api::serial::STOP_BITS_ONE; | 401 : device::serial::STOP_BITS_ONE; |
401 info->cts_flow_control.reset(new bool((config.c_cflag & CRTSCTS) != 0)); | 402 info->cts_flow_control = (config.c_cflag & CRTSCTS) != 0; |
402 return true; | 403 return info.Pass(); |
403 } | 404 } |
404 | 405 |
405 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 406 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
406 return port_name; | 407 return port_name; |
407 } | 408 } |
408 | 409 |
409 } // namespace extensions | 410 } // namespace extensions |
OLD | NEW |