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"
10 #include "base/stl_util.h"
11 #include "device/core/device_client.h"
12 #include "device/hid/hid_connection.h"
13 #include "device/hid/hid_device_filter.h"
14 #include "device/hid/hid_device_info.h"
15 #include "device/hid/hid_service.h"
16 #include "extensions/browser/api/api_resource_manager.h"
17 #include "extensions/common/api/hid.h"
18 #include "net/base/io_buffer.h"
20 namespace hid
= extensions::core_api::hid
;
22 using device::HidConnection
;
23 using device::HidDeviceFilter
;
24 using device::HidDeviceInfo
;
25 using device::HidService
;
29 const char kErrorServiceUnavailable
[] = "HID services are unavailable.";
30 const char kErrorPermissionDenied
[] = "Permission to access device was denied.";
31 const char kErrorInvalidDeviceId
[] = "Invalid HID device ID.";
32 const char kErrorFailedToOpenDevice
[] = "Failed to open HID device.";
33 const char kErrorConnectionNotFound
[] = "Connection not established.";
34 const char kErrorTransfer
[] = "Transfer failed.";
36 base::Value
* PopulateHidConnection(int connection_id
,
37 scoped_refptr
<HidConnection
> connection
) {
38 hid::HidConnectInfo connection_value
;
39 connection_value
.connection_id
= connection_id
;
40 return connection_value
.ToValue().release();
43 void ConvertHidDeviceFilter(linked_ptr
<hid::DeviceFilter
> input
,
44 HidDeviceFilter
* output
) {
45 if (input
->vendor_id
) {
46 output
->SetVendorId(*input
->vendor_id
);
48 if (input
->product_id
) {
49 output
->SetProductId(*input
->product_id
);
51 if (input
->usage_page
) {
52 output
->SetUsagePage(*input
->usage_page
);
55 output
->SetUsage(*input
->usage
);
61 namespace extensions
{
63 HidGetDevicesFunction::HidGetDevicesFunction() {}
65 HidGetDevicesFunction::~HidGetDevicesFunction() {}
67 ExtensionFunction::ResponseAction
HidGetDevicesFunction::Run() {
68 scoped_ptr
<core_api::hid::GetDevices::Params
> parameters
=
69 hid::GetDevices::Params::Create(*args_
);
70 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
72 HidDeviceManager
* device_manager
= HidDeviceManager::Get(browser_context());
73 if (!device_manager
) {
74 return RespondNow(Error(kErrorServiceUnavailable
));
77 std::vector
<HidDeviceFilter
> filters
;
78 if (parameters
->options
.filters
) {
79 filters
.resize(parameters
->options
.filters
->size());
80 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
81 ConvertHidDeviceFilter(parameters
->options
.filters
->at(i
), &filters
[i
]);
84 if (parameters
->options
.vendor_id
) {
85 HidDeviceFilter legacy_filter
;
86 legacy_filter
.SetVendorId(*parameters
->options
.vendor_id
);
87 if (parameters
->options
.product_id
) {
88 legacy_filter
.SetProductId(*parameters
->options
.product_id
);
90 filters
.push_back(legacy_filter
);
93 device_manager
->GetApiDevices(
95 base::Bind(&HidGetDevicesFunction::OnEnumerationComplete
, this));
96 return RespondLater();
99 void HidGetDevicesFunction::OnEnumerationComplete(
100 scoped_ptr
<base::ListValue
> devices
) {
101 Respond(OneArgument(devices
.release()));
104 HidConnectFunction::HidConnectFunction() : connection_manager_(nullptr) {
107 HidConnectFunction::~HidConnectFunction() {}
109 ExtensionFunction::ResponseAction
HidConnectFunction::Run() {
110 scoped_ptr
<core_api::hid::Connect::Params
> parameters
=
111 hid::Connect::Params::Create(*args_
);
112 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
114 HidDeviceManager
* device_manager
= HidDeviceManager::Get(browser_context());
115 if (!device_manager
) {
116 return RespondNow(Error(kErrorServiceUnavailable
));
119 connection_manager_
=
120 ApiResourceManager
<HidConnectionResource
>::Get(browser_context());
121 if (!connection_manager_
) {
122 return RespondNow(Error(kErrorServiceUnavailable
));
125 scoped_refptr
<HidDeviceInfo
> device_info
=
126 device_manager
->GetDeviceInfo(parameters
->device_id
);
128 return RespondNow(Error(kErrorInvalidDeviceId
));
131 if (!HidDeviceManager::HasPermission(extension(), device_info
)) {
132 return RespondNow(Error(kErrorPermissionDenied
));
135 HidService
* hid_service
= device::DeviceClient::Get()->GetHidService();
137 return RespondNow(Error(kErrorServiceUnavailable
));
140 hid_service
->Connect(
141 device_info
->device_id(),
142 base::Bind(&HidConnectFunction::OnConnectComplete
, this));
143 return RespondLater();
146 void HidConnectFunction::OnConnectComplete(
147 scoped_refptr
<HidConnection
> connection
) {
148 if (!connection
.get()) {
149 Respond(Error(kErrorFailedToOpenDevice
));
153 DCHECK(connection_manager_
);
154 int connection_id
= connection_manager_
->Add(
155 new HidConnectionResource(extension_id(), connection
));
156 Respond(OneArgument(PopulateHidConnection(connection_id
, connection
)));
159 HidDisconnectFunction::HidDisconnectFunction() {}
161 HidDisconnectFunction::~HidDisconnectFunction() {}
163 ExtensionFunction::ResponseAction
HidDisconnectFunction::Run() {
164 scoped_ptr
<core_api::hid::Disconnect::Params
> parameters
=
165 hid::Disconnect::Params::Create(*args_
);
166 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
168 ApiResourceManager
<HidConnectionResource
>* connection_manager
=
169 ApiResourceManager
<HidConnectionResource
>::Get(browser_context());
170 if (!connection_manager
) {
171 return RespondNow(Error(kErrorServiceUnavailable
));
174 int connection_id
= parameters
->connection_id
;
175 HidConnectionResource
* resource
=
176 connection_manager
->Get(extension_id(), connection_id
);
178 return RespondNow(Error(kErrorConnectionNotFound
));
181 connection_manager
->Remove(extension_id(), connection_id
);
182 return RespondNow(NoArguments());
185 HidConnectionIoFunction::HidConnectionIoFunction() {
188 HidConnectionIoFunction::~HidConnectionIoFunction() {
191 ExtensionFunction::ResponseAction
HidConnectionIoFunction::Run() {
192 if (!ValidateParameters()) {
193 return RespondNow(Error(error_
));
196 ApiResourceManager
<HidConnectionResource
>* connection_manager
=
197 ApiResourceManager
<HidConnectionResource
>::Get(browser_context());
198 if (!connection_manager
) {
199 return RespondNow(Error(kErrorServiceUnavailable
));
202 HidConnectionResource
* resource
=
203 connection_manager
->Get(extension_id(), connection_id_
);
205 return RespondNow(Error(kErrorConnectionNotFound
));
208 StartWork(resource
->connection().get());
209 return RespondLater();
212 HidReceiveFunction::HidReceiveFunction() {}
214 HidReceiveFunction::~HidReceiveFunction() {}
216 bool HidReceiveFunction::ValidateParameters() {
217 parameters_
= hid::Receive::Params::Create(*args_
);
218 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
219 set_connection_id(parameters_
->connection_id
);
223 void HidReceiveFunction::StartWork(HidConnection
* connection
) {
224 connection
->Read(base::Bind(&HidReceiveFunction::OnFinished
, this));
227 void HidReceiveFunction::OnFinished(bool success
,
228 scoped_refptr
<net::IOBuffer
> buffer
,
232 int report_id
= reinterpret_cast<uint8_t*>(buffer
->data())[0];
234 Respond(TwoArguments(new base::FundamentalValue(report_id
),
235 base::BinaryValue::CreateWithCopiedBuffer(
236 buffer
->data() + 1, size
- 1)));
238 Respond(Error(kErrorTransfer
));
242 HidSendFunction::HidSendFunction() {}
244 HidSendFunction::~HidSendFunction() {}
246 bool HidSendFunction::ValidateParameters() {
247 parameters_
= hid::Send::Params::Create(*args_
);
248 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
249 set_connection_id(parameters_
->connection_id
);
253 void HidSendFunction::StartWork(HidConnection
* connection
) {
254 scoped_refptr
<net::IOBufferWithSize
> buffer(
255 new net::IOBufferWithSize(parameters_
->data
.size() + 1));
256 buffer
->data()[0] = static_cast<uint8_t>(parameters_
->report_id
);
257 memcpy(buffer
->data() + 1, parameters_
->data
.data(),
258 parameters_
->data
.size());
259 connection
->Write(buffer
, buffer
->size(),
260 base::Bind(&HidSendFunction::OnFinished
, this));
263 void HidSendFunction::OnFinished(bool success
) {
265 Respond(NoArguments());
267 Respond(Error(kErrorTransfer
));
271 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {}
273 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {}
275 bool HidReceiveFeatureReportFunction::ValidateParameters() {
276 parameters_
= hid::ReceiveFeatureReport::Params::Create(*args_
);
277 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
278 set_connection_id(parameters_
->connection_id
);
282 void HidReceiveFeatureReportFunction::StartWork(HidConnection
* connection
) {
283 connection
->GetFeatureReport(
284 static_cast<uint8_t>(parameters_
->report_id
),
285 base::Bind(&HidReceiveFeatureReportFunction::OnFinished
, this));
288 void HidReceiveFeatureReportFunction::OnFinished(
290 scoped_refptr
<net::IOBuffer
> buffer
,
294 base::BinaryValue::CreateWithCopiedBuffer(buffer
->data(), size
)));
296 Respond(Error(kErrorTransfer
));
300 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {}
302 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {}
304 bool HidSendFeatureReportFunction::ValidateParameters() {
305 parameters_
= hid::SendFeatureReport::Params::Create(*args_
);
306 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
307 set_connection_id(parameters_
->connection_id
);
311 void HidSendFeatureReportFunction::StartWork(HidConnection
* connection
) {
312 scoped_refptr
<net::IOBufferWithSize
> buffer(
313 new net::IOBufferWithSize(parameters_
->data
.size() + 1));
314 buffer
->data()[0] = static_cast<uint8_t>(parameters_
->report_id
);
315 memcpy(buffer
->data() + 1, vector_as_array(¶meters_
->data
),
316 parameters_
->data
.size());
317 connection
->SendFeatureReport(
318 buffer
, buffer
->size(),
319 base::Bind(&HidSendFeatureReportFunction::OnFinished
, this));
322 void HidSendFeatureReportFunction::OnFinished(bool success
) {
324 Respond(NoArguments());
326 Respond(Error(kErrorTransfer
));
330 } // namespace extensions