Add chrome.usb.getConfiguration and expose extra descriptors.
[chromium-blink-merge.git] / extensions / browser / api / hid / hid_api.cc
blob99cf1bd253f1a5415287da44039f8abed98f5821
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.
5 #include "extensions/browser/api/hid/hid_api.h"
7 #include <string>
8 #include <vector>
10 #include "device/core/device_client.h"
11 #include "device/hid/hid_connection.h"
12 #include "device/hid/hid_device_filter.h"
13 #include "device/hid/hid_device_info.h"
14 #include "device/hid/hid_service.h"
15 #include "extensions/browser/api/api_resource_manager.h"
16 #include "extensions/common/api/hid.h"
17 #include "net/base/io_buffer.h"
19 namespace hid = extensions::core_api::hid;
21 using device::HidConnection;
22 using device::HidDeviceFilter;
23 using device::HidDeviceInfo;
24 using device::HidService;
26 namespace {
28 const char kErrorPermissionDenied[] = "Permission to access device was denied.";
29 const char kErrorInvalidDeviceId[] = "Invalid HID device ID.";
30 const char kErrorFailedToOpenDevice[] = "Failed to open HID device.";
31 const char kErrorConnectionNotFound[] = "Connection not established.";
32 const char kErrorTransfer[] = "Transfer failed.";
34 base::Value* PopulateHidConnection(int connection_id,
35 scoped_refptr<HidConnection> connection) {
36 hid::HidConnectInfo connection_value;
37 connection_value.connection_id = connection_id;
38 return connection_value.ToValue().release();
41 void ConvertHidDeviceFilter(linked_ptr<hid::DeviceFilter> input,
42 HidDeviceFilter* output) {
43 if (input->vendor_id) {
44 output->SetVendorId(*input->vendor_id);
46 if (input->product_id) {
47 output->SetProductId(*input->product_id);
49 if (input->usage_page) {
50 output->SetUsagePage(*input->usage_page);
52 if (input->usage) {
53 output->SetUsage(*input->usage);
57 } // namespace
59 namespace extensions {
61 HidAsyncApiFunction::HidAsyncApiFunction()
62 : device_manager_(NULL), connection_manager_(NULL) {}
64 HidAsyncApiFunction::~HidAsyncApiFunction() {}
66 bool HidAsyncApiFunction::PrePrepare() {
67 device_manager_ = HidDeviceManager::Get(browser_context());
68 DCHECK(device_manager_);
69 connection_manager_ =
70 ApiResourceManager<HidConnectionResource>::Get(browser_context());
71 DCHECK(connection_manager_);
72 set_work_thread_id(content::BrowserThread::FILE);
73 return true;
76 bool HidAsyncApiFunction::Respond() { return error_.empty(); }
78 HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource(
79 int api_resource_id) {
80 return connection_manager_->Get(extension_->id(), api_resource_id);
83 void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) {
84 connection_manager_->Remove(extension_->id(), api_resource_id);
87 void HidAsyncApiFunction::CompleteWithError(const std::string& error) {
88 SetError(error);
89 AsyncWorkCompleted();
92 HidGetDevicesFunction::HidGetDevicesFunction() {}
94 HidGetDevicesFunction::~HidGetDevicesFunction() {}
96 bool HidGetDevicesFunction::Prepare() {
97 parameters_ = hid::GetDevices::Params::Create(*args_);
98 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
99 return true;
102 void HidGetDevicesFunction::AsyncWorkStart() {
103 std::vector<HidDeviceFilter> filters;
104 if (parameters_->options.filters) {
105 filters.resize(parameters_->options.filters->size());
106 for (size_t i = 0; i < parameters_->options.filters->size(); ++i) {
107 ConvertHidDeviceFilter(parameters_->options.filters->at(i), &filters[i]);
110 if (parameters_->options.vendor_id) {
111 HidDeviceFilter legacy_filter;
112 legacy_filter.SetVendorId(*parameters_->options.vendor_id);
113 if (parameters_->options.product_id) {
114 legacy_filter.SetProductId(*parameters_->options.product_id);
116 filters.push_back(legacy_filter);
119 SetResult(device_manager_->GetApiDevices(extension(), filters).release());
120 AsyncWorkCompleted();
123 HidConnectFunction::HidConnectFunction() {}
125 HidConnectFunction::~HidConnectFunction() {}
127 bool HidConnectFunction::Prepare() {
128 parameters_ = hid::Connect::Params::Create(*args_);
129 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
130 return true;
133 void HidConnectFunction::AsyncWorkStart() {
134 device::HidDeviceInfo device_info;
135 if (!device_manager_->GetDeviceInfo(parameters_->device_id, &device_info)) {
136 CompleteWithError(kErrorInvalidDeviceId);
137 return;
140 if (!device_manager_->HasPermission(extension(), device_info)) {
141 LOG(WARNING) << "Insufficient permissions to access device.";
142 CompleteWithError(kErrorPermissionDenied);
143 return;
146 HidService* hid_service = device::DeviceClient::Get()->GetHidService();
147 DCHECK(hid_service);
148 scoped_refptr<HidConnection> connection =
149 hid_service->Connect(device_info.device_id);
150 if (!connection.get()) {
151 CompleteWithError(kErrorFailedToOpenDevice);
152 return;
154 int connection_id = connection_manager_->Add(
155 new HidConnectionResource(extension_->id(), connection));
156 SetResult(PopulateHidConnection(connection_id, connection));
157 AsyncWorkCompleted();
160 HidDisconnectFunction::HidDisconnectFunction() {}
162 HidDisconnectFunction::~HidDisconnectFunction() {}
164 bool HidDisconnectFunction::Prepare() {
165 parameters_ = hid::Disconnect::Params::Create(*args_);
166 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
167 return true;
170 void HidDisconnectFunction::AsyncWorkStart() {
171 int connection_id = parameters_->connection_id;
172 HidConnectionResource* resource =
173 connection_manager_->Get(extension_->id(), connection_id);
174 if (!resource) {
175 CompleteWithError(kErrorConnectionNotFound);
176 return;
178 connection_manager_->Remove(extension_->id(), connection_id);
179 AsyncWorkCompleted();
182 HidReceiveFunction::HidReceiveFunction() {}
184 HidReceiveFunction::~HidReceiveFunction() {}
186 bool HidReceiveFunction::Prepare() {
187 parameters_ = hid::Receive::Params::Create(*args_);
188 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
189 return true;
192 void HidReceiveFunction::AsyncWorkStart() {
193 int connection_id = parameters_->connection_id;
194 HidConnectionResource* resource =
195 connection_manager_->Get(extension_->id(), connection_id);
196 if (!resource) {
197 CompleteWithError(kErrorConnectionNotFound);
198 return;
201 scoped_refptr<device::HidConnection> connection = resource->connection();
202 connection->Read(base::Bind(&HidReceiveFunction::OnFinished, this));
205 void HidReceiveFunction::OnFinished(bool success,
206 scoped_refptr<net::IOBuffer> buffer,
207 size_t size) {
208 if (!success) {
209 CompleteWithError(kErrorTransfer);
210 return;
213 DCHECK_GE(size, 1u);
214 int report_id = reinterpret_cast<uint8_t*>(buffer->data())[0];
216 scoped_ptr<base::ListValue> result(new base::ListValue());
217 result->Append(new base::FundamentalValue(report_id));
218 result->Append(
219 base::BinaryValue::CreateWithCopiedBuffer(buffer->data() + 1, size - 1));
220 SetResultList(result.Pass());
221 AsyncWorkCompleted();
224 HidSendFunction::HidSendFunction() {}
226 HidSendFunction::~HidSendFunction() {}
228 bool HidSendFunction::Prepare() {
229 parameters_ = hid::Send::Params::Create(*args_);
230 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
231 return true;
234 void HidSendFunction::AsyncWorkStart() {
235 int connection_id = parameters_->connection_id;
236 HidConnectionResource* resource =
237 connection_manager_->Get(extension_->id(), connection_id);
238 if (!resource) {
239 CompleteWithError(kErrorConnectionNotFound);
240 return;
243 scoped_refptr<net::IOBufferWithSize> buffer(
244 new net::IOBufferWithSize(parameters_->data.size() + 1));
245 buffer->data()[0] = static_cast<uint8_t>(parameters_->report_id);
246 memcpy(
247 buffer->data() + 1, parameters_->data.c_str(), parameters_->data.size());
248 resource->connection()->Write(
249 buffer, buffer->size(), base::Bind(&HidSendFunction::OnFinished, this));
252 void HidSendFunction::OnFinished(bool success) {
253 if (!success) {
254 CompleteWithError(kErrorTransfer);
255 return;
257 AsyncWorkCompleted();
260 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {}
262 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {}
264 bool HidReceiveFeatureReportFunction::Prepare() {
265 parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_);
266 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
267 return true;
270 void HidReceiveFeatureReportFunction::AsyncWorkStart() {
271 int connection_id = parameters_->connection_id;
272 HidConnectionResource* resource =
273 connection_manager_->Get(extension_->id(), connection_id);
274 if (!resource) {
275 CompleteWithError(kErrorConnectionNotFound);
276 return;
279 scoped_refptr<device::HidConnection> connection = resource->connection();
280 connection->GetFeatureReport(
281 static_cast<uint8_t>(parameters_->report_id),
282 base::Bind(&HidReceiveFeatureReportFunction::OnFinished, this));
285 void HidReceiveFeatureReportFunction::OnFinished(
286 bool success,
287 scoped_refptr<net::IOBuffer> buffer,
288 size_t size) {
289 if (!success) {
290 CompleteWithError(kErrorTransfer);
291 return;
294 SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer->data(), size));
295 AsyncWorkCompleted();
298 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {}
300 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {}
302 bool HidSendFeatureReportFunction::Prepare() {
303 parameters_ = hid::SendFeatureReport::Params::Create(*args_);
304 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
305 return true;
308 void HidSendFeatureReportFunction::AsyncWorkStart() {
309 int connection_id = parameters_->connection_id;
310 HidConnectionResource* resource =
311 connection_manager_->Get(extension_->id(), connection_id);
312 if (!resource) {
313 CompleteWithError(kErrorConnectionNotFound);
314 return;
317 scoped_refptr<net::IOBufferWithSize> buffer(
318 new net::IOBufferWithSize(parameters_->data.size() + 1));
319 buffer->data()[0] = static_cast<uint8_t>(parameters_->report_id);
320 memcpy(
321 buffer->data() + 1, parameters_->data.c_str(), parameters_->data.size());
322 resource->connection()->SendFeatureReport(
323 buffer,
324 buffer->size(),
325 base::Bind(&HidSendFeatureReportFunction::OnFinished, this));
328 void HidSendFeatureReportFunction::OnFinished(bool success) {
329 if (!success) {
330 CompleteWithError(kErrorTransfer);
331 return;
333 AsyncWorkCompleted();
336 } // namespace extensions