Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/hid/hid_connection_mac.h" | 5 #include "device/hid/hid_connection_mac.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/mac/foundation_util.h" | 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "device/hid/hid_connection_mac.h" | 10 #include "device/hid/hid_connection_mac.h" |
| 11 | 11 |
| 12 namespace device { | 12 namespace device { |
| 13 | 13 |
| 14 HidConnectionMac::HidConnectionMac(HidDeviceInfo device_info) | 14 HidConnectionMac::HidConnectionMac(HidDeviceInfo device_info) |
| 15 : HidConnection(device_info), | 15 : HidConnection(device_info), |
| 16 device_(device_info.device_id, base::scoped_policy::RETAIN) { | 16 device_(device_info.device_id, base::scoped_policy::RETAIN) { |
| 17 message_loop_ = base::MessageLoopProxy::current(); | 17 message_loop_ = base::MessageLoopProxy::current(); |
| 18 | 18 |
| 19 DCHECK(device_.get()); | 19 DCHECK(device_.get()); |
| 20 | |
| 20 size_t expected_report_size = device_info.max_input_report_size; | 21 size_t expected_report_size = device_info.max_input_report_size; |
| 21 if (device_info.has_report_id) { | 22 if (device_info.has_report_id) { |
| 22 expected_report_size++; | 23 expected_report_size++; |
| 23 } | 24 } |
| 24 inbound_buffer_.reset(new uint8_t[expected_report_size]); | 25 inbound_buffer_.resize(expected_report_size); |
| 25 IOHIDDeviceRegisterInputReportCallback(device_.get(), | 26 if (inbound_buffer_.size() > 0) { |
| 26 inbound_buffer_.get(), | 27 IOHIDDeviceRegisterInputReportCallback( |
| 27 expected_report_size, | 28 device_.get(), |
| 28 &HidConnectionMac::InputReportCallback, | 29 &inbound_buffer_[0], |
| 29 this); | 30 inbound_buffer_.size(), |
| 30 IOHIDDeviceOpen(device_, kIOHIDOptionsTypeNone); | 31 &HidConnectionMac::InputReportCallback, |
| 32 this); | |
| 33 } | |
| 31 } | 34 } |
| 32 | 35 |
| 33 HidConnectionMac::~HidConnectionMac() { | 36 HidConnectionMac::~HidConnectionMac() { |
| 34 IOHIDDeviceClose(device_, kIOHIDOptionsTypeNone); | 37 if (inbound_buffer_.size() > 0) { |
| 38 IOHIDDeviceRegisterInputReportCallback( | |
|
Ken Rockot(use gerrit already)
2014/09/13 01:36:17
Can you please comment on why this is done? I do n
Reilly Grant (use Gerrit)
2014/09/13 05:05:05
Registering a NULL callback clears the input repor
| |
| 39 device_.get(), &inbound_buffer_[0], inbound_buffer_.size(), NULL, this); | |
| 40 } | |
| 35 Flush(); | 41 Flush(); |
| 36 } | 42 } |
| 37 | 43 |
| 38 void HidConnectionMac::PlatformRead(const ReadCallback& callback) { | 44 void HidConnectionMac::PlatformRead(const ReadCallback& callback) { |
| 39 if (!device_) { | 45 if (!device_) { |
| 40 callback.Run(false, NULL, 0); | 46 callback.Run(false, NULL, 0); |
| 41 return; | 47 return; |
| 42 } | 48 } |
| 43 | 49 |
| 44 PendingHidRead pending_read; | 50 PendingHidRead pending_read; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 65 CFIndex report_size = buffer->size(); | 71 CFIndex report_size = buffer->size(); |
| 66 IOReturn result = | 72 IOReturn result = |
| 67 IOHIDDeviceGetReport(device_, | 73 IOHIDDeviceGetReport(device_, |
| 68 kIOHIDReportTypeFeature, | 74 kIOHIDReportTypeFeature, |
| 69 report_id, | 75 report_id, |
| 70 reinterpret_cast<uint8_t*>(buffer->data()), | 76 reinterpret_cast<uint8_t*>(buffer->data()), |
| 71 &report_size); | 77 &report_size); |
| 72 if (result == kIOReturnSuccess) { | 78 if (result == kIOReturnSuccess) { |
| 73 callback.Run(true, buffer, report_size); | 79 callback.Run(true, buffer, report_size); |
| 74 } else { | 80 } else { |
| 81 VLOG(1) << "Failed to get feature report: " << result; | |
| 75 callback.Run(false, NULL, 0); | 82 callback.Run(false, NULL, 0); |
| 76 } | 83 } |
| 77 } | 84 } |
| 78 | 85 |
| 79 void HidConnectionMac::PlatformSendFeatureReport( | 86 void HidConnectionMac::PlatformSendFeatureReport( |
| 80 scoped_refptr<net::IOBuffer> buffer, | 87 scoped_refptr<net::IOBuffer> buffer, |
| 81 size_t size, | 88 size_t size, |
| 82 const WriteCallback& callback) { | 89 const WriteCallback& callback) { |
| 83 WriteReport(kIOHIDReportTypeFeature, buffer, size, callback); | 90 WriteReport(kIOHIDReportTypeFeature, buffer, size, callback); |
| 84 } | 91 } |
| 85 | 92 |
| 86 void HidConnectionMac::InputReportCallback(void* context, | 93 void HidConnectionMac::InputReportCallback(void* context, |
| 87 IOReturn result, | 94 IOReturn result, |
| 88 void* sender, | 95 void* sender, |
| 89 IOHIDReportType type, | 96 IOHIDReportType type, |
| 90 uint32_t report_id, | 97 uint32_t report_id, |
| 91 uint8_t* report_bytes, | 98 uint8_t* report_bytes, |
| 92 CFIndex report_length) { | 99 CFIndex report_length) { |
| 100 if (result != kIOReturnSuccess) { | |
| 101 VLOG(1) << "Failed to read input report: " << result; | |
| 102 return; | |
| 103 } | |
| 104 | |
| 93 HidConnectionMac* connection = static_cast<HidConnectionMac*>(context); | 105 HidConnectionMac* connection = static_cast<HidConnectionMac*>(context); |
| 94 scoped_refptr<net::IOBufferWithSize> buffer; | 106 scoped_refptr<net::IOBufferWithSize> buffer; |
| 95 if (connection->device_info().has_report_id) { | 107 if (connection->device_info().has_report_id) { |
| 96 // report_id is already contained in report_bytes | 108 // report_id is already contained in report_bytes |
| 97 buffer = new net::IOBufferWithSize(report_length); | 109 buffer = new net::IOBufferWithSize(report_length); |
| 98 memcpy(buffer->data(), report_bytes, report_length); | 110 memcpy(buffer->data(), report_bytes, report_length); |
| 99 } else { | 111 } else { |
| 100 buffer = new net::IOBufferWithSize(report_length + 1); | 112 buffer = new net::IOBufferWithSize(report_length + 1); |
| 101 buffer->data()[0] = 0; | 113 buffer->data()[0] = 0; |
| 102 memcpy(buffer->data() + 1, report_bytes, report_length); | 114 memcpy(buffer->data() + 1, report_bytes, report_length); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 124 // report ID is non-zero. | 136 // report ID is non-zero. |
| 125 ++data; | 137 ++data; |
| 126 --size; | 138 --size; |
| 127 } | 139 } |
| 128 | 140 |
| 129 IOReturn res = | 141 IOReturn res = |
| 130 IOHIDDeviceSetReport(device_.get(), type, report_id, data, size); | 142 IOHIDDeviceSetReport(device_.get(), type, report_id, data, size); |
| 131 if (res == kIOReturnSuccess) { | 143 if (res == kIOReturnSuccess) { |
| 132 callback.Run(true); | 144 callback.Run(true); |
| 133 } else { | 145 } else { |
| 146 VLOG(1) << "Failed to set report: " << res; | |
| 134 callback.Run(false); | 147 callback.Run(false); |
| 135 } | 148 } |
| 136 } | 149 } |
| 137 | 150 |
| 138 void HidConnectionMac::Flush() { | 151 void HidConnectionMac::Flush() { |
| 139 while (!pending_reads_.empty()) { | 152 while (!pending_reads_.empty()) { |
| 140 pending_reads_.front().callback.Run(false, NULL, 0); | 153 pending_reads_.front().callback.Run(false, NULL, 0); |
| 141 pending_reads_.pop(); | 154 pending_reads_.pop(); |
| 142 } | 155 } |
| 143 } | 156 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 159 PendingHidReport report = pending_reports_.front(); | 172 PendingHidReport report = pending_reports_.front(); |
| 160 | 173 |
| 161 pending_reports_.pop(); | 174 pending_reports_.pop(); |
| 162 if (CompleteRead(report.buffer, report.size, read.callback)) { | 175 if (CompleteRead(report.buffer, report.size, read.callback)) { |
| 163 pending_reads_.pop(); | 176 pending_reads_.pop(); |
| 164 } | 177 } |
| 165 } | 178 } |
| 166 } | 179 } |
| 167 | 180 |
| 168 } // namespace device | 181 } // namespace device |
| OLD | NEW |