1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/serial/serial_api.h" 6 7 #include <algorithm> 8 9 #include "base/values.h" 10 #include "chrome/browser/extensions/extension_system.h" 11 #include "chrome/browser/extensions/api/serial/serial_connection.h" 12 #include "chrome/browser/extensions/api/serial/serial_event_dispatcher.h" 13 #include "chrome/browser/extensions/api/serial/serial_port_enumerator.h" 14 #include "chrome/common/extensions/api/serial.h" 15 #include "content/public/browser/browser_thread.h" 16 17 using content::BrowserThread; 18 19 namespace extensions { 20 21 namespace 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() 53 : manager_(NULL) { 54 } 55 56 SerialAsyncApiFunction::~SerialAsyncApiFunction() {} 57 58 bool SerialAsyncApiFunction::PrePrepare() { 59 manager_ = ApiResourceManager<SerialConnection>::Get(GetProfile()); 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 bool SerialGetDevicesFunction::Prepare() { 80 set_work_thread_id(BrowserThread::FILE); 81 return true; 82 } 83 84 void SerialGetDevicesFunction::Work() { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 86 87 std::vector<linked_ptr<serial::DeviceInfo> > devices; 88 SerialPortEnumerator::StringSet port_names = 89 SerialPortEnumerator::GenerateValidSerialPortNames(); 90 for (SerialPortEnumerator::StringSet::const_iterator iter = 91 port_names.begin(); 92 iter != port_names.end(); 93 ++iter) { 94 linked_ptr<serial::DeviceInfo> info(new serial::DeviceInfo); 95 info->path = *iter; 96 devices.push_back(info); 97 } 98 results_ = serial::GetDevices::Results::Create(devices); 99 } 100 101 SerialConnectFunction::SerialConnectFunction() {} 102 103 SerialConnectFunction::~SerialConnectFunction() {} 104 105 bool SerialConnectFunction::Prepare() { 106 params_ = serial::Connect::Params::Create(*args_); 107 EXTENSION_FUNCTION_VALIDATE(params_.get()); 108 109 // Fill in any omitted options to ensure a known initial configuration. 110 if (!params_->options.get()) 111 params_->options.reset(new serial::ConnectionOptions()); 112 serial::ConnectionOptions* options = params_->options.get(); 113 114 SetDefaultScopedPtrValue(options->persistent, false); 115 SetDefaultScopedPtrValue(options->buffer_size, kDefaultBufferSize); 116 SetDefaultScopedPtrValue(options->bitrate, kDefaultBitrate); 117 SetDefaultScopedPtrValue(options->cts_flow_control, false); 118 SetDefaultScopedPtrValue(options->receive_timeout, kDefaultReceiveTimeout); 119 SetDefaultScopedPtrValue(options->send_timeout, kDefaultSendTimeout); 120 121 if (options->data_bits == serial::DATA_BITS_NONE) 122 options->data_bits = kDefaultDataBits; 123 if (options->parity_bit == serial::PARITY_BIT_NONE) 124 options->parity_bit = kDefaultParityBit; 125 if (options->stop_bits == serial::STOP_BITS_NONE) 126 options->stop_bits = kDefaultStopBits; 127 128 serial_event_dispatcher_ = SerialEventDispatcher::Get(GetProfile()); 129 DCHECK(serial_event_dispatcher_); 130 131 return true; 132 } 133 134 void SerialConnectFunction::AsyncWorkStart() { 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 136 connection_ = CreateSerialConnection(params_->path, extension_->id()); 137 connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this)); 138 } 139 140 void SerialConnectFunction::OnConnected(bool success) { 141 DCHECK(connection_); 142 143 if (success) { 144 if (!connection_->Configure(*params_->options.get())) { 145 connection_->Close(); 146 delete connection_; 147 connection_ = NULL; 148 } 149 } else { 150 delete connection_; 151 connection_ = NULL; 152 } 153 154 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 155 base::Bind(&SerialConnectFunction::FinishConnect, 156 this)); 157 } 158 159 void SerialConnectFunction::FinishConnect() { 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 161 if (!connection_) { 162 error_ = kErrorConnectFailed; 163 } else { 164 int id = manager_->Add(connection_); 165 serial::ConnectionInfo info; 166 info.connection_id = id; 167 if (connection_->GetInfo(&info)) { 168 serial_event_dispatcher_->PollConnection(extension_->id(), id); 169 results_ = serial::Connect::Results::Create(info); 170 } else { 171 connection_->Close(); 172 RemoveSerialConnection(id); 173 error_ = kErrorConnectFailed; 174 } 175 } 176 AsyncWorkCompleted(); 177 } 178 179 SerialConnection* SerialConnectFunction::CreateSerialConnection( 180 const std::string& port, const std::string& extension_id) const { 181 return new SerialConnection(port, extension_id); 182 } 183 184 SerialUpdateFunction::SerialUpdateFunction() {} 185 186 SerialUpdateFunction::~SerialUpdateFunction() {} 187 188 bool SerialUpdateFunction::Prepare() { 189 params_ = serial::Update::Params::Create(*args_); 190 EXTENSION_FUNCTION_VALIDATE(params_.get()); 191 192 return true; 193 } 194 195 void SerialUpdateFunction::Work() { 196 SerialConnection* connection = GetSerialConnection(params_->connection_id); 197 if (!connection) { 198 error_ = kErrorSerialConnectionNotFound; 199 return; 200 } 201 bool success = connection->Configure(params_->options); 202 results_ = serial::Update::Results::Create(success); 203 } 204 205 SerialDisconnectFunction::SerialDisconnectFunction() {} 206 207 SerialDisconnectFunction::~SerialDisconnectFunction() {} 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 connection->Close(); 223 RemoveSerialConnection(params_->connection_id); 224 results_ = serial::Disconnect::Results::Create(true); 225 } 226 227 SerialSendFunction::SerialSendFunction() {} 228 229 SerialSendFunction::~SerialSendFunction() {} 230 231 bool SerialSendFunction::Prepare() { 232 params_ = serial::Send::Params::Create(*args_); 233 EXTENSION_FUNCTION_VALIDATE(params_.get()); 234 235 return true; 236 } 237 238 void SerialSendFunction::AsyncWorkStart() { 239 SerialConnection* connection = GetSerialConnection(params_->connection_id); 240 if (!connection) { 241 error_ = kErrorSerialConnectionNotFound; 242 AsyncWorkCompleted(); 243 return; 244 } 245 246 if (!connection->Send(params_->data, 247 base::Bind(&SerialSendFunction::OnSendComplete, 248 this))) { 249 OnSendComplete(0, serial::SEND_ERROR_PENDING); 250 } 251 } 252 253 void SerialSendFunction::OnSendComplete(int bytes_sent, 254 serial::SendError error) { 255 serial::SendInfo send_info; 256 send_info.bytes_sent = bytes_sent; 257 send_info.error = error; 258 results_ = serial::Send::Results::Create(send_info); 259 AsyncWorkCompleted(); 260 } 261 262 SerialFlushFunction::SerialFlushFunction() {} 263 264 SerialFlushFunction::~SerialFlushFunction() {} 265 266 bool SerialFlushFunction::Prepare() { 267 params_ = serial::Flush::Params::Create(*args_); 268 EXTENSION_FUNCTION_VALIDATE(params_.get()); 269 return true; 270 } 271 272 void SerialFlushFunction::Work() { 273 SerialConnection* connection = GetSerialConnection(params_->connection_id); 274 if (!connection) { 275 error_ = kErrorSerialConnectionNotFound; 276 return; 277 } 278 279 bool success = connection->Flush(); 280 results_ = serial::Flush::Results::Create(success); 281 } 282 283 SerialSetPausedFunction::SerialSetPausedFunction() {} 284 285 SerialSetPausedFunction::~SerialSetPausedFunction() {} 286 287 bool SerialSetPausedFunction::Prepare() { 288 params_ = serial::SetPaused::Params::Create(*args_); 289 EXTENSION_FUNCTION_VALIDATE(params_.get()); 290 291 serial_event_dispatcher_ = SerialEventDispatcher::Get(GetProfile()); 292 DCHECK(serial_event_dispatcher_); 293 return true; 294 } 295 296 void SerialSetPausedFunction::Work() { 297 SerialConnection* connection = GetSerialConnection(params_->connection_id); 298 if (!connection) { 299 error_ = kErrorSerialConnectionNotFound; 300 return; 301 } 302 303 if (params_->paused != connection->paused()) { 304 connection->set_paused(params_->paused); 305 if (!params_->paused) { 306 serial_event_dispatcher_->PollConnection(extension_->id(), 307 params_->connection_id); 308 } 309 } 310 311 results_ = serial::SetPaused::Results::Create(); 312 } 313 314 SerialGetInfoFunction::SerialGetInfoFunction() {} 315 316 SerialGetInfoFunction::~SerialGetInfoFunction() {} 317 318 bool SerialGetInfoFunction::Prepare() { 319 params_ = serial::GetInfo::Params::Create(*args_); 320 EXTENSION_FUNCTION_VALIDATE(params_.get()); 321 322 return true; 323 } 324 325 void SerialGetInfoFunction::Work() { 326 SerialConnection* connection = GetSerialConnection(params_->connection_id); 327 if (!connection) { 328 error_ = kErrorSerialConnectionNotFound; 329 return; 330 } 331 332 serial::ConnectionInfo info; 333 info.connection_id = params_->connection_id; 334 connection->GetInfo(&info); 335 results_ = serial::GetInfo::Results::Create(info); 336 } 337 338 SerialGetConnectionsFunction::SerialGetConnectionsFunction() {} 339 340 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {} 341 342 bool SerialGetConnectionsFunction::Prepare() { 343 return true; 344 } 345 346 void SerialGetConnectionsFunction::Work() { 347 std::vector<linked_ptr<serial::ConnectionInfo> > infos; 348 const base::hash_set<int>* connection_ids = manager_->GetResourceIds( 349 extension_->id()); 350 if (connection_ids) { 351 for (base::hash_set<int>::const_iterator it = connection_ids->begin(); 352 it != connection_ids->end(); ++it) { 353 int connection_id = *it; 354 SerialConnection *connection = GetSerialConnection(connection_id); 355 if (connection) { 356 linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo()); 357 info->connection_id = connection_id; 358 connection->GetInfo(info.get()); 359 infos.push_back(info); 360 } 361 } 362 } 363 results_ = serial::GetConnections::Results::Create(infos); 364 } 365 366 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {} 367 368 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {} 369 370 bool SerialGetControlSignalsFunction::Prepare() { 371 params_ = serial::GetControlSignals::Params::Create(*args_); 372 EXTENSION_FUNCTION_VALIDATE(params_.get()); 373 374 return true; 375 } 376 377 void SerialGetControlSignalsFunction::Work() { 378 SerialConnection* connection = GetSerialConnection(params_->connection_id); 379 if (!connection) { 380 error_ = kErrorSerialConnectionNotFound; 381 return; 382 } 383 384 serial::DeviceControlSignals signals; 385 if (!connection->GetControlSignals(&signals)) { 386 error_ = kErrorGetControlSignalsFailed; 387 return; 388 } 389 390 results_ = serial::GetControlSignals::Results::Create(signals); 391 } 392 393 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {} 394 395 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {} 396 397 bool SerialSetControlSignalsFunction::Prepare() { 398 params_ = serial::SetControlSignals::Params::Create(*args_); 399 EXTENSION_FUNCTION_VALIDATE(params_.get()); 400 401 return true; 402 } 403 404 void SerialSetControlSignalsFunction::Work() { 405 SerialConnection* connection = GetSerialConnection(params_->connection_id); 406 if (!connection) { 407 error_ = kErrorSerialConnectionNotFound; 408 return; 409 } 410 411 bool success = connection->SetControlSignals(params_->signals); 412 results_ = serial::SetControlSignals::Results::Create(success); 413 } 414 415 } // namespace api 416 417 } // namespace extensions 418