Home | History | Annotate | Download | only in serial
      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