Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1582)

Unified Diff: device/hid/hid_connection_win.cc

Issue 143883005: HID backend (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hid-impl-base
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: device/hid/hid_connection_win.cc
diff --git a/device/hid/hid_connection_win.cc b/device/hid/hid_connection_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eba31e1701fc66aec313fdf65d243b7485cc60cf
--- /dev/null
+++ b/device/hid/hid_connection_win.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/hid/hid_connection_win.h"
+
+#include <cstring>
+
+#include "base/threading/thread_restrictions.h"
+#include "device/hid/hid_service.h"
+#include "device/hid/hid_service_win.h"
+#include "net/base/io_buffer.h"
+
+#if defined(OS_WIN)
+
+#define INITGUID
+
+#include <windows.h>
+#include <hidclass.h>
+
+extern "C" {
+
+#include <hidsdi.h>
+
+}
+
+#include <setupapi.h>
+#include <winioctl.h>
+#include "base/win/scoped_handle.h"
+
+#endif // defined(OS_WIN)
+
+namespace device {
+
+AsyncTransfer::AsyncTransfer(HANDLE file,
+ scoped_refptr<net::IOBuffer> buffer,
+ const HidIOCallback& callback,
+ bool is_read)
+ : file_(file),
+ buffer_(buffer),
+ callback_(callback),
+ actual_size_(0),
+ is_read_(is_read) {
+ memset(&overlapped_, 0, sizeof(OVERLAPPED));
+ event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
+ overlapped_.hEvent = event_.Get();
+}
+
+AsyncTransfer::~AsyncTransfer() {
+}
+
+void AsyncTransfer::StartWatching(BOOL result_from_winapi) {
+ if (!result_from_winapi) {
+ if (GetLastError() == ERROR_IO_PENDING) {
+ if (watcher_.StartWatching(event_.Get(), this)) {
+ AddRef();
+ } else {
+ callback_.Run(false, NULL, 0);
+ }
+ } else {
+ PLOG(ERROR) << "HidConnectionWin::Read";
+ callback_.Run(false, NULL, 0);
+ }
+ } else {
+ AddRef();
+ OnObjectSignaled(overlapped_.hEvent);
+ }
+}
+
+OVERLAPPED* AsyncTransfer::GetOverlappedPtr() {
+ return &overlapped_;
+}
+
+DWORD* AsyncTransfer::GetActualSizePtr() {
+ return &actual_size_;
+}
+
+void AsyncTransfer::OnObjectSignaled(HANDLE object) {
+ DCHECK_EQ(object, event_.Get());
+ BOOL result = GetOverlappedResult(file_,&overlapped_, &actual_size_, FALSE);
+
+ // For input transfers, if the first byte is zero, we need to remove it.
+ if (is_read_ && buffer_->data()[0] == 0) {
+ actual_size_--;
+ memmove(buffer_->data(), buffer_->data() + 1, actual_size_);
+ }
+ callback_.Run(result != 0, buffer_, (size_t)actual_size_);
+ Release();
+}
+
+HidConnectionWin::HidConnectionWin(HidDeviceInfo device_info)
+ : HidConnection(device_info),
+ available_(false) {
+ file_.Set(CreateFileA(device_info.device_id.c_str(),
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL));
+ available_ = file_.Get() != INVALID_HANDLE_VALUE;
+}
+
+HidConnectionWin::~HidConnectionWin() {}
+
+void HidConnectionWin::Read(const HidIOCallback& callback) {
+ size_t report_size = device_info_.input_report_size;
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_size));
+ scoped_refptr<AsyncTransfer> aync_transfer(
+ new AsyncTransfer(file_, buffer, callback, true));
+
+ aync_transfer->StartWatching(ReadFile(file_.Get(),
+ buffer->data(),
+ report_size,
+ aync_transfer->GetActualSizePtr(),
+ aync_transfer->GetOverlappedPtr()));
+}
+
+void HidConnectionWin::Write(scoped_refptr<net::IOBuffer> buffer,
+ size_t size,
+ const HidIOCallback& callback) {
+ size_t report_size = device_info_.output_report_size;
+ if (size < report_size) {
+ scoped_refptr<net::IOBuffer> expanded_buffer(
+ new net::IOBuffer(report_size));
+ memset(expanded_buffer->data(), 0, report_size);
+ memcpy(expanded_buffer->data(), buffer->data(), size);
+ size = report_size;
+ buffer = expanded_buffer;
+ }
+
+ scoped_refptr<AsyncTransfer> aync_transfer(
+ new AsyncTransfer(file_, NULL, callback, false));
+
+ aync_transfer->StartWatching(WriteFile(file_,
+ buffer->data(),
+ size,
+ aync_transfer->GetActualSizePtr(),
+ aync_transfer->GetOverlappedPtr()));
+}
+
+void HidConnectionWin::GetFeatureReport(const HidIOCallback& callback) {
+ size_t report_size = device_info_.feature_report_size;
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_size));
+ scoped_refptr<AsyncTransfer> aync_transfer(
+ new AsyncTransfer(file_, buffer, callback, true));
+
+ aync_transfer->
+ StartWatching(DeviceIoControl(file_,
+ IOCTL_HID_GET_FEATURE,
+ NULL, 0,
+ buffer->data(), report_size,
+ aync_transfer->GetActualSizePtr(),
+ aync_transfer->GetOverlappedPtr()));
+}
+
+void HidConnectionWin::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
+ size_t size,
+ const HidIOCallback& callback) {
+ size_t report_size = device_info_.feature_report_size;
+ if (size < report_size) {
+ scoped_refptr<net::IOBuffer> expanded_buffer(
+ new net::IOBuffer(report_size));
+ memset(expanded_buffer->data(), 0, report_size);
+ memcpy(expanded_buffer->data(), buffer->data(), size);
+ size = report_size;
+ buffer = expanded_buffer;
+ }
+
+ scoped_refptr<AsyncTransfer> aync_transfer(
+ new AsyncTransfer(file_, NULL, callback, false));
+
+ aync_transfer->
+ StartWatching(DeviceIoControl(file_,
+ IOCTL_HID_SET_FEATURE,
+ buffer->data(), report_size,
+ NULL, 0,
+ aync_transfer->GetActualSizePtr(),
+ aync_transfer->GetOverlappedPtr()));
+}
+
+} // namespace device

Powered by Google App Engine
This is Rietveld 408576698