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 3 // found in the LICENSE file. 4 5 #include "extensions/browser/api/serial/serial_api.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/values.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "device/serial/serial_device_enumerator.h" 13 #include "extensions/browser/api/serial/serial_connection.h" 14 #include "extensions/browser/api/serial/serial_event_dispatcher.h" 15 #include "extensions/common/api/serial.h" 16 17 using content::BrowserThread; 18 19 namespace extensions { 20 21 namespace core_api { 22 23 namespace { 24 25 // It's a fool's errand to come up with a default bitrate, because we don't get 26 // to control both sides of the communication. Unless the other side has 27 // implemented auto-bitrate detection (rare), if we pick the wrong rate, then 28 // you're gonna have a bad time. Close doesn't count. 29 // 30 // But we'd like to pick something that has a chance of working, and 9600 is a 31 // good balance between popularity and speed. So 9600 it is. 32 const int kDefaultBufferSize = 4096; 33 const int kDefaultBitrate = 9600; 34 const serial::DataBits kDefaultDataBits = serial::DATA_BITS_EIGHT; 35 const serial::ParityBit kDefaultParityBit = serial::PARITY_BIT_NO; 36 const serial::StopBits kDefaultStopBits = serial::STOP_BITS_ONE; 37 const int kDefaultReceiveTimeout = 0; 38 const int kDefaultSendTimeout = 0; 39 40 const char kErrorConnectFailed[] = "Failed to connect to the port."; 41 const char kErrorSerialConnectionNotFound[] = "Serial connection not found."; 42 const char kErrorGetControlSignalsFailed[] = "Failed to get control signals."; 43 44 template <class T> 45 void SetDefaultScopedPtrValue(scoped_ptr<T>& ptr, const T& value) { 46 if (!ptr.get()) 47 ptr.reset(new T(value)); 48 } 49 50 } // namespace 51 52 SerialAsyncApiFunction::SerialAsyncApiFunction() : manager_(NULL) { 53 } 54 55 SerialAsyncApiFunction::~SerialAsyncApiFunction() { 56 } 57 58 bool SerialAsyncApiFunction::PrePrepare() { 59 manager_ = ApiResourceManager<SerialConnection>::Get(browser_context()); 60 DCHECK(manager_); 61 return true; 62 } 63 64 bool SerialAsyncApiFunction::Respond() { 65 return error_.empty(); 66 } 67 68 SerialConnection* SerialAsyncApiFunction::GetSerialConnection( 69 int api_resource_id) { 70 return manager_->Get(extension_->id(), api_resource_id); 71 } 72 73 void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) { 74 manager_->Remove(extension_->id(), api_resource_id); 75 } 76 77 SerialGetDevicesFunction::SerialGetDevicesFunction() { 78 } 79 80 bool SerialGetDevicesFunction::Prepare() { 81 set_work_thread_id(BrowserThread::FILE); 82 return true; 83 } 84 85 void SerialGetDevicesFunction::Work() { 86 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 87 88 scoped_ptr<device::SerialDeviceEnumerator> enumerator = 89 device::SerialDeviceEnumerator::Create(); 90 mojo::Array<device::serial::DeviceInfoPtr> devices = enumerator->GetDevices(); 91 results_ = serial::GetDevices::Results::Create( 92 devices.To<std::vector<linked_ptr<serial::DeviceInfo> > >()); 93 } 94 95 SerialConnectFunction::SerialConnectFunction() { 96 } 97 98 SerialConnectFunction::~SerialConnectFunction() { 99 } 100 101 bool SerialConnectFunction::Prepare() { 102 params_ = serial::Connect::Params::Create(*args_); 103 EXTENSION_FUNCTION_VALIDATE(params_.get()); 104 105 // Fill in any omitted options to ensure a known initial configuration. 106 if (!params_->options.get()) 107 params_->options.reset(new serial::ConnectionOptions()); 108 serial::ConnectionOptions* options = params_->options.get(); 109 110 SetDefaultScopedPtrValue(options->persistent, false); 111 SetDefaultScopedPtrValue(options->buffer_size, kDefaultBufferSize); 112 SetDefaultScopedPtrValue(options->bitrate, kDefaultBitrate); 113 SetDefaultScopedPtrValue(options->cts_flow_control, false); 114 SetDefaultScopedPtrValue(options->receive_timeout, kDefaultReceiveTimeout); 115 SetDefaultScopedPtrValue(options->send_timeout, kDefaultSendTimeout); 116 117 if (options->data_bits == serial::DATA_BITS_NONE) 118 options->data_bits = kDefaultDataBits; 119 if (options->parity_bit == serial::PARITY_BIT_NONE) 120 options->parity_bit = kDefaultParityBit; 121 if (options->stop_bits == serial::STOP_BITS_NONE) 122 options->stop_bits = kDefaultStopBits; 123 124 serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context()); 125 DCHECK(serial_event_dispatcher_); 126 127 return true; 128 } 129 130 void SerialConnectFunction::AsyncWorkStart() { 131 DCHECK_CURRENTLY_ON(BrowserThread::IO); 132 connection_ = CreateSerialConnection(params_->path, extension_->id()); 133 connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this)); 134 } 135 136 void SerialConnectFunction::OnConnected(bool success) { 137 DCHECK(connection_); 138 139 if (success) { 140 if (!connection_->Configure(*params_->options.get())) { 141 delete connection_; 142 connection_ = NULL; 143 } 144 } else { 145 delete connection_; 146 connection_ = NULL; 147 } 148 149 BrowserThread::PostTask( 150 BrowserThread::IO, 151 FROM_HERE, 152 base::Bind(&SerialConnectFunction::FinishConnect, this)); 153 } 154 155 void SerialConnectFunction::FinishConnect() { 156 DCHECK_CURRENTLY_ON(BrowserThread::IO); 157 if (!connection_) { 158 error_ = kErrorConnectFailed; 159 } else { 160 int id = manager_->Add(connection_); 161 serial::ConnectionInfo info; 162 info.connection_id = id; 163 if (connection_->GetInfo(&info)) { 164 serial_event_dispatcher_->PollConnection(extension_->id(), id); 165 results_ = serial::Connect::Results::Create(info); 166 } else { 167 RemoveSerialConnection(id); 168 error_ = kErrorConnectFailed; 169 } 170 } 171 AsyncWorkCompleted(); 172 } 173 174 SerialConnection* SerialConnectFunction::CreateSerialConnection( 175 const std::string& port, 176 const std::string& extension_id) const { 177 return new SerialConnection(port, extension_id); 178 } 179 180 SerialUpdateFunction::SerialUpdateFunction() { 181 } 182 183 SerialUpdateFunction::~SerialUpdateFunction() { 184 } 185 186 bool SerialUpdateFunction::Prepare() { 187 params_ = serial::Update::Params::Create(*args_); 188 EXTENSION_FUNCTION_VALIDATE(params_.get()); 189 190 return true; 191 } 192 193 void SerialUpdateFunction::Work() { 194 SerialConnection* connection = GetSerialConnection(params_->connection_id); 195 if (!connection) { 196 error_ = kErrorSerialConnectionNotFound; 197 return; 198 } 199 bool success = connection->Configure(params_->options); 200 results_ = serial::Update::Results::Create(success); 201 } 202 203 SerialDisconnectFunction::SerialDisconnectFunction() { 204 } 205 206 SerialDisconnectFunction::~SerialDisconnectFunction() { 207 } 208 209 bool SerialDisconnectFunction::Prepare() { 210 params_ = serial::Disconnect::Params::Create(*args_); 211 EXTENSION_FUNCTION_VALIDATE(params_.get()); 212 213 return true; 214 } 215 216 void SerialDisconnectFunction::Work() { 217 SerialConnection* connection = GetSerialConnection(params_->connection_id); 218 if (!connection) { 219 error_ = kErrorSerialConnectionNotFound; 220 return; 221 } 222 RemoveSerialConnection(params_->connection_id); 223 results_ = serial::Disconnect::Results::Create(true); 224 } 225 226 SerialSendFunction::SerialSendFunction() { 227 } 228 229 SerialSendFunction::~SerialSendFunction() { 230 } 231 232 bool SerialSendFunction::Prepare() { 233 params_ = serial::Send::Params::Create(*args_); 234 EXTENSION_FUNCTION_VALIDATE(params_.get()); 235 236 return true; 237 } 238 239 void SerialSendFunction::AsyncWorkStart() { 240 SerialConnection* connection = GetSerialConnection(params_->connection_id); 241 if (!connection) { 242 error_ = kErrorSerialConnectionNotFound; 243 AsyncWorkCompleted(); 244 return; 245 } 246 247 if (!connection->Send( 248 params_->data, 249 base::Bind(&SerialSendFunction::OnSendComplete, this))) { 250 OnSendComplete(0, serial::SEND_ERROR_PENDING); 251 } 252 } 253 254 void SerialSendFunction::OnSendComplete(int bytes_sent, 255 serial::SendError error) { 256 serial::SendInfo send_info; 257 send_info.bytes_sent = bytes_sent; 258 send_info.error = error; 259 results_ = serial::Send::Results::Create(send_info); 260 AsyncWorkCompleted(); 261 } 262 263 SerialFlushFunction::SerialFlushFunction() { 264 } 265 266 SerialFlushFunction::~SerialFlushFunction() { 267 } 268 269 bool SerialFlushFunction::Prepare() { 270 params_ = serial::Flush::Params::Create(*args_); 271 EXTENSION_FUNCTION_VALIDATE(params_.get()); 272 return true; 273 } 274 275 void SerialFlushFunction::Work() { 276 SerialConnection* connection = GetSerialConnection(params_->connection_id); 277 if (!connection) { 278 error_ = kErrorSerialConnectionNotFound; 279 return; 280 } 281 282 bool success = connection->Flush(); 283 results_ = serial::Flush::Results::Create(success); 284 } 285 286 SerialSetPausedFunction::SerialSetPausedFunction() { 287 } 288 289 SerialSetPausedFunction::~SerialSetPausedFunction() { 290 } 291 292 bool SerialSetPausedFunction::Prepare() { 293 params_ = serial::SetPaused::Params::Create(*args_); 294 EXTENSION_FUNCTION_VALIDATE(params_.get()); 295 296 serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context()); 297 DCHECK(serial_event_dispatcher_); 298 return true; 299 } 300 301 void SerialSetPausedFunction::Work() { 302 SerialConnection* connection = GetSerialConnection(params_->connection_id); 303 if (!connection) { 304 error_ = kErrorSerialConnectionNotFound; 305 return; 306 } 307 308 if (params_->paused != connection->paused()) { 309 connection->set_paused(params_->paused); 310 if (!params_->paused) { 311 serial_event_dispatcher_->PollConnection(extension_->id(), 312 params_->connection_id); 313 } 314 } 315 316 results_ = serial::SetPaused::Results::Create(); 317 } 318 319 SerialGetInfoFunction::SerialGetInfoFunction() { 320 } 321 322 SerialGetInfoFunction::~SerialGetInfoFunction() { 323 } 324 325 bool SerialGetInfoFunction::Prepare() { 326 params_ = serial::GetInfo::Params::Create(*args_); 327 EXTENSION_FUNCTION_VALIDATE(params_.get()); 328 329 return true; 330 } 331 332 void SerialGetInfoFunction::Work() { 333 SerialConnection* connection = GetSerialConnection(params_->connection_id); 334 if (!connection) { 335 error_ = kErrorSerialConnectionNotFound; 336 return; 337 } 338 339 serial::ConnectionInfo info; 340 info.connection_id = params_->connection_id; 341 connection->GetInfo(&info); 342 results_ = serial::GetInfo::Results::Create(info); 343 } 344 345 SerialGetConnectionsFunction::SerialGetConnectionsFunction() { 346 } 347 348 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() { 349 } 350 351 bool SerialGetConnectionsFunction::Prepare() { 352 return true; 353 } 354 355 void SerialGetConnectionsFunction::Work() { 356 std::vector<linked_ptr<serial::ConnectionInfo> > infos; 357 const base::hash_set<int>* connection_ids = 358 manager_->GetResourceIds(extension_->id()); 359 if (connection_ids) { 360 for (base::hash_set<int>::const_iterator it = connection_ids->begin(); 361 it != connection_ids->end(); 362 ++it) { 363 int connection_id = *it; 364 SerialConnection* connection = GetSerialConnection(connection_id); 365 if (connection) { 366 linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo()); 367 info->connection_id = connection_id; 368 connection->GetInfo(info.get()); 369 infos.push_back(info); 370 } 371 } 372 } 373 results_ = serial::GetConnections::Results::Create(infos); 374 } 375 376 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() { 377 } 378 379 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() { 380 } 381 382 bool SerialGetControlSignalsFunction::Prepare() { 383 params_ = serial::GetControlSignals::Params::Create(*args_); 384 EXTENSION_FUNCTION_VALIDATE(params_.get()); 385 386 return true; 387 } 388 389 void SerialGetControlSignalsFunction::Work() { 390 SerialConnection* connection = GetSerialConnection(params_->connection_id); 391 if (!connection) { 392 error_ = kErrorSerialConnectionNotFound; 393 return; 394 } 395 396 serial::DeviceControlSignals signals; 397 if (!connection->GetControlSignals(&signals)) { 398 error_ = kErrorGetControlSignalsFailed; 399 return; 400 } 401 402 results_ = serial::GetControlSignals::Results::Create(signals); 403 } 404 405 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() { 406 } 407 408 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() { 409 } 410 411 bool SerialSetControlSignalsFunction::Prepare() { 412 params_ = serial::SetControlSignals::Params::Create(*args_); 413 EXTENSION_FUNCTION_VALIDATE(params_.get()); 414 415 return true; 416 } 417 418 void SerialSetControlSignalsFunction::Work() { 419 SerialConnection* connection = GetSerialConnection(params_->connection_id); 420 if (!connection) { 421 error_ = kErrorSerialConnectionNotFound; 422 return; 423 } 424 425 bool success = connection->SetControlSignals(params_->signals); 426 results_ = serial::SetControlSignals::Results::Create(success); 427 } 428 429 } // namespace core_api 430 431 } // namespace extensions 432 433 namespace mojo { 434 435 // static 436 linked_ptr<extensions::core_api::serial::DeviceInfo> TypeConverter< 437 linked_ptr<extensions::core_api::serial::DeviceInfo>, 438 device::serial::DeviceInfoPtr>::Convert(const device::serial::DeviceInfoPtr& 439 device) { 440 linked_ptr<extensions::core_api::serial::DeviceInfo> info( 441 new extensions::core_api::serial::DeviceInfo); 442 info->path = device->path; 443 if (device->has_vendor_id) 444 info->vendor_id.reset(new int(static_cast<int>(device->vendor_id))); 445 if (device->has_product_id) 446 info->product_id.reset(new int(static_cast<int>(device->product_id))); 447 if (device->display_name) 448 info->display_name.reset(new std::string(device->display_name)); 449 return info; 450 } 451 452 } // namespace mojo 453