1 // Copyright 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.
5 #include "chrome/browser/extensions/api/serial/serial_api.h"
9 #include "base/values.h"
10 #include "chrome/browser/extensions/api/serial/serial_connection.h"
11 #include "chrome/browser/extensions/api/serial/serial_event_dispatcher.h"
12 #include "chrome/common/extensions/api/serial.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "device/serial/serial_device_enumerator.h"
15 #include "extensions/browser/extension_system.h"
17 using content::BrowserThread;
19 namespace extensions {
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.
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;
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.";
45 void SetDefaultScopedPtrValue(scoped_ptr<T>& ptr, const T& value) {
47 ptr.reset(new T(value));
52 SerialAsyncApiFunction::SerialAsyncApiFunction()
56 SerialAsyncApiFunction::~SerialAsyncApiFunction() {}
58 bool SerialAsyncApiFunction::PrePrepare() {
59 manager_ = ApiResourceManager<SerialConnection>::Get(GetProfile());
64 bool SerialAsyncApiFunction::Respond() {
65 return error_.empty();
68 SerialConnection* SerialAsyncApiFunction::GetSerialConnection(
69 int api_resource_id) {
70 return manager_->Get(extension_->id(), api_resource_id);
73 void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) {
74 manager_->Remove(extension_->id(), api_resource_id);
77 SerialGetDevicesFunction::SerialGetDevicesFunction() {}
79 bool SerialGetDevicesFunction::Prepare() {
80 set_work_thread_id(BrowserThread::FILE);
84 void SerialGetDevicesFunction::Work() {
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
87 device::SerialDeviceInfoList devices;
88 scoped_ptr<device::SerialDeviceEnumerator> enumerator =
89 device::SerialDeviceEnumerator::Create();
90 enumerator->GetDevices(&devices);
92 std::vector<linked_ptr<serial::DeviceInfo> > out_devices;
93 for (device::SerialDeviceInfoList::const_iterator iter = devices.begin();
94 iter != devices.end();
96 linked_ptr<device::SerialDeviceInfo> device = *iter;
97 linked_ptr<serial::DeviceInfo> info(new serial::DeviceInfo);
98 info->path = device->path;
99 if (device->vendor_id)
100 info->vendor_id.reset(new int(static_cast<int>(*device->vendor_id)));
101 if (device->product_id)
102 info->product_id.reset(new int(static_cast<int>(*device->product_id)));
103 info->display_name.reset(device->display_name.release());
104 out_devices.push_back(info);
107 results_ = serial::GetDevices::Results::Create(out_devices);
110 SerialConnectFunction::SerialConnectFunction() {}
112 SerialConnectFunction::~SerialConnectFunction() {}
114 bool SerialConnectFunction::Prepare() {
115 params_ = serial::Connect::Params::Create(*args_);
116 EXTENSION_FUNCTION_VALIDATE(params_.get());
118 // Fill in any omitted options to ensure a known initial configuration.
119 if (!params_->options.get())
120 params_->options.reset(new serial::ConnectionOptions());
121 serial::ConnectionOptions* options = params_->options.get();
123 SetDefaultScopedPtrValue(options->persistent, false);
124 SetDefaultScopedPtrValue(options->buffer_size, kDefaultBufferSize);
125 SetDefaultScopedPtrValue(options->bitrate, kDefaultBitrate);
126 SetDefaultScopedPtrValue(options->cts_flow_control, false);
127 SetDefaultScopedPtrValue(options->receive_timeout, kDefaultReceiveTimeout);
128 SetDefaultScopedPtrValue(options->send_timeout, kDefaultSendTimeout);
130 if (options->data_bits == serial::DATA_BITS_NONE)
131 options->data_bits = kDefaultDataBits;
132 if (options->parity_bit == serial::PARITY_BIT_NONE)
133 options->parity_bit = kDefaultParityBit;
134 if (options->stop_bits == serial::STOP_BITS_NONE)
135 options->stop_bits = kDefaultStopBits;
137 serial_event_dispatcher_ = SerialEventDispatcher::Get(GetProfile());
138 DCHECK(serial_event_dispatcher_);
143 void SerialConnectFunction::AsyncWorkStart() {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
145 connection_ = CreateSerialConnection(params_->path, extension_->id());
146 connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this));
149 void SerialConnectFunction::OnConnected(bool success) {
153 if (!connection_->Configure(*params_->options.get())) {
154 connection_->Close();
163 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
164 base::Bind(&SerialConnectFunction::FinishConnect,
168 void SerialConnectFunction::FinishConnect() {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
171 error_ = kErrorConnectFailed;
173 int id = manager_->Add(connection_);
174 serial::ConnectionInfo info;
175 info.connection_id = id;
176 if (connection_->GetInfo(&info)) {
177 serial_event_dispatcher_->PollConnection(extension_->id(), id);
178 results_ = serial::Connect::Results::Create(info);
180 connection_->Close();
181 RemoveSerialConnection(id);
182 error_ = kErrorConnectFailed;
185 AsyncWorkCompleted();
188 SerialConnection* SerialConnectFunction::CreateSerialConnection(
189 const std::string& port, const std::string& extension_id) const {
190 return new SerialConnection(port, extension_id);
193 SerialUpdateFunction::SerialUpdateFunction() {}
195 SerialUpdateFunction::~SerialUpdateFunction() {}
197 bool SerialUpdateFunction::Prepare() {
198 params_ = serial::Update::Params::Create(*args_);
199 EXTENSION_FUNCTION_VALIDATE(params_.get());
204 void SerialUpdateFunction::Work() {
205 SerialConnection* connection = GetSerialConnection(params_->connection_id);
207 error_ = kErrorSerialConnectionNotFound;
210 bool success = connection->Configure(params_->options);
211 results_ = serial::Update::Results::Create(success);
214 SerialDisconnectFunction::SerialDisconnectFunction() {}
216 SerialDisconnectFunction::~SerialDisconnectFunction() {}
218 bool SerialDisconnectFunction::Prepare() {
219 params_ = serial::Disconnect::Params::Create(*args_);
220 EXTENSION_FUNCTION_VALIDATE(params_.get());
225 void SerialDisconnectFunction::Work() {
226 SerialConnection* connection = GetSerialConnection(params_->connection_id);
228 error_ = kErrorSerialConnectionNotFound;
232 RemoveSerialConnection(params_->connection_id);
233 results_ = serial::Disconnect::Results::Create(true);
236 SerialSendFunction::SerialSendFunction() {}
238 SerialSendFunction::~SerialSendFunction() {}
240 bool SerialSendFunction::Prepare() {
241 params_ = serial::Send::Params::Create(*args_);
242 EXTENSION_FUNCTION_VALIDATE(params_.get());
247 void SerialSendFunction::AsyncWorkStart() {
248 SerialConnection* connection = GetSerialConnection(params_->connection_id);
250 error_ = kErrorSerialConnectionNotFound;
251 AsyncWorkCompleted();
255 if (!connection->Send(params_->data,
256 base::Bind(&SerialSendFunction::OnSendComplete,
258 OnSendComplete(0, serial::SEND_ERROR_PENDING);
262 void SerialSendFunction::OnSendComplete(int bytes_sent,
263 serial::SendError error) {
264 serial::SendInfo send_info;
265 send_info.bytes_sent = bytes_sent;
266 send_info.error = error;
267 results_ = serial::Send::Results::Create(send_info);
268 AsyncWorkCompleted();
271 SerialFlushFunction::SerialFlushFunction() {}
273 SerialFlushFunction::~SerialFlushFunction() {}
275 bool SerialFlushFunction::Prepare() {
276 params_ = serial::Flush::Params::Create(*args_);
277 EXTENSION_FUNCTION_VALIDATE(params_.get());
281 void SerialFlushFunction::Work() {
282 SerialConnection* connection = GetSerialConnection(params_->connection_id);
284 error_ = kErrorSerialConnectionNotFound;
288 bool success = connection->Flush();
289 results_ = serial::Flush::Results::Create(success);
292 SerialSetPausedFunction::SerialSetPausedFunction() {}
294 SerialSetPausedFunction::~SerialSetPausedFunction() {}
296 bool SerialSetPausedFunction::Prepare() {
297 params_ = serial::SetPaused::Params::Create(*args_);
298 EXTENSION_FUNCTION_VALIDATE(params_.get());
300 serial_event_dispatcher_ = SerialEventDispatcher::Get(GetProfile());
301 DCHECK(serial_event_dispatcher_);
305 void SerialSetPausedFunction::Work() {
306 SerialConnection* connection = GetSerialConnection(params_->connection_id);
308 error_ = kErrorSerialConnectionNotFound;
312 if (params_->paused != connection->paused()) {
313 connection->set_paused(params_->paused);
314 if (!params_->paused) {
315 serial_event_dispatcher_->PollConnection(extension_->id(),
316 params_->connection_id);
320 results_ = serial::SetPaused::Results::Create();
323 SerialGetInfoFunction::SerialGetInfoFunction() {}
325 SerialGetInfoFunction::~SerialGetInfoFunction() {}
327 bool SerialGetInfoFunction::Prepare() {
328 params_ = serial::GetInfo::Params::Create(*args_);
329 EXTENSION_FUNCTION_VALIDATE(params_.get());
334 void SerialGetInfoFunction::Work() {
335 SerialConnection* connection = GetSerialConnection(params_->connection_id);
337 error_ = kErrorSerialConnectionNotFound;
341 serial::ConnectionInfo info;
342 info.connection_id = params_->connection_id;
343 connection->GetInfo(&info);
344 results_ = serial::GetInfo::Results::Create(info);
347 SerialGetConnectionsFunction::SerialGetConnectionsFunction() {}
349 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {}
351 bool SerialGetConnectionsFunction::Prepare() {
355 void SerialGetConnectionsFunction::Work() {
356 std::vector<linked_ptr<serial::ConnectionInfo> > infos;
357 const base::hash_set<int>* connection_ids = manager_->GetResourceIds(
359 if (connection_ids) {
360 for (base::hash_set<int>::const_iterator it = connection_ids->begin();
361 it != connection_ids->end(); ++it) {
362 int connection_id = *it;
363 SerialConnection *connection = GetSerialConnection(connection_id);
365 linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo());
366 info->connection_id = connection_id;
367 connection->GetInfo(info.get());
368 infos.push_back(info);
372 results_ = serial::GetConnections::Results::Create(infos);
375 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {}
377 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {}
379 bool SerialGetControlSignalsFunction::Prepare() {
380 params_ = serial::GetControlSignals::Params::Create(*args_);
381 EXTENSION_FUNCTION_VALIDATE(params_.get());
386 void SerialGetControlSignalsFunction::Work() {
387 SerialConnection* connection = GetSerialConnection(params_->connection_id);
389 error_ = kErrorSerialConnectionNotFound;
393 serial::DeviceControlSignals signals;
394 if (!connection->GetControlSignals(&signals)) {
395 error_ = kErrorGetControlSignalsFailed;
399 results_ = serial::GetControlSignals::Results::Create(signals);
402 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {}
404 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {}
406 bool SerialSetControlSignalsFunction::Prepare() {
407 params_ = serial::SetControlSignals::Params::Create(*args_);
408 EXTENSION_FUNCTION_VALIDATE(params_.get());
413 void SerialSetControlSignalsFunction::Work() {
414 SerialConnection* connection = GetSerialConnection(params_->connection_id);
416 error_ = kErrorSerialConnectionNotFound;
420 bool success = connection->SetControlSignals(params_->signals);
421 results_ = serial::SetControlSignals::Results::Create(success);
426 } // namespace extensions