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

Side by Side Diff: device/hid/hid_connection_mac.cc

Issue 499713002: Don't pass buffers to HidConnection::Read because it knows the size. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed rockot@'s nits. Created 6 years, 3 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 unified diff | Download patch
« no previous file with comments | « device/hid/hid_connection_mac.h ('k') | device/hid/hid_connection_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 size_t expected_report_size = device_info.max_input_report_size; 20 size_t expected_report_size = device_info.max_input_report_size;
21 if (device_info.has_report_id) { 21 if (device_info.has_report_id) {
22 expected_report_size++; 22 expected_report_size++;
23 } 23 }
24 inbound_buffer_.reset((uint8_t*)malloc(expected_report_size)); 24 inbound_buffer_.reset(new uint8_t[expected_report_size]);
25 IOHIDDeviceRegisterInputReportCallback(device_.get(), 25 IOHIDDeviceRegisterInputReportCallback(device_.get(),
26 inbound_buffer_.get(), 26 inbound_buffer_.get(),
27 expected_report_size, 27 expected_report_size,
28 &HidConnectionMac::InputReportCallback, 28 &HidConnectionMac::InputReportCallback,
29 this); 29 this);
30 IOHIDDeviceOpen(device_, kIOHIDOptionsTypeNone); 30 IOHIDDeviceOpen(device_, kIOHIDOptionsTypeNone);
31 } 31 }
32 32
33 HidConnectionMac::~HidConnectionMac() { 33 HidConnectionMac::~HidConnectionMac() {
34 IOHIDDeviceClose(device_, kIOHIDOptionsTypeNone); 34 IOHIDDeviceClose(device_, kIOHIDOptionsTypeNone);
35 Flush(); 35 Flush();
36 } 36 }
37 37
38 void HidConnectionMac::PlatformRead(scoped_refptr<net::IOBufferWithSize> buffer, 38 void HidConnectionMac::PlatformRead(const ReadCallback& callback) {
39 const IOCallback& callback) {
40 if (!device_) { 39 if (!device_) {
41 callback.Run(false, 0); 40 callback.Run(false, NULL, 0);
42 return; 41 return;
43 } 42 }
44 43
45 PendingHidRead pending_read; 44 PendingHidRead pending_read;
46 pending_read.buffer = buffer;
47 pending_read.callback = callback; 45 pending_read.callback = callback;
48 pending_reads_.push(pending_read); 46 pending_reads_.push(pending_read);
49 ProcessReadQueue(); 47 ProcessReadQueue();
50 } 48 }
51 49
52 void HidConnectionMac::PlatformWrite( 50 void HidConnectionMac::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
53 uint8_t report_id, 51 size_t size,
54 scoped_refptr<net::IOBufferWithSize> buffer, 52 const WriteCallback& callback) {
55 const IOCallback& callback) { 53 WriteReport(kIOHIDReportTypeOutput, buffer, size, callback);
56 WriteReport(kIOHIDReportTypeOutput, report_id, buffer, callback);
57 } 54 }
58 55
59 void HidConnectionMac::PlatformGetFeatureReport( 56 void HidConnectionMac::PlatformGetFeatureReport(uint8_t report_id,
60 uint8_t report_id, 57 const ReadCallback& callback) {
61 scoped_refptr<net::IOBufferWithSize> buffer,
62 const IOCallback& callback) {
63 if (!device_) { 58 if (!device_) {
64 callback.Run(false, 0); 59 callback.Run(false, NULL, 0);
65 return; 60 return;
66 } 61 }
67 62
68 uint8_t* feature_report_buffer = reinterpret_cast<uint8_t*>(buffer->data()); 63 scoped_refptr<net::IOBufferWithSize> buffer(
64 new net::IOBufferWithSize(device_info().max_feature_report_size));
69 CFIndex report_size = buffer->size(); 65 CFIndex report_size = buffer->size();
70 IOReturn result = IOHIDDeviceGetReport(device_, 66 IOReturn result =
71 kIOHIDReportTypeFeature, 67 IOHIDDeviceGetReport(device_,
72 report_id, 68 kIOHIDReportTypeFeature,
73 feature_report_buffer, 69 report_id,
74 &report_size); 70 reinterpret_cast<uint8_t*>(buffer->data()),
75 if (result == kIOReturnSuccess) 71 &report_size);
76 callback.Run(true, report_size); 72 if (result == kIOReturnSuccess) {
77 else 73 callback.Run(true, buffer, report_size);
78 callback.Run(false, 0); 74 } else {
75 callback.Run(false, NULL, 0);
76 }
79 } 77 }
80 78
81 void HidConnectionMac::PlatformSendFeatureReport( 79 void HidConnectionMac::PlatformSendFeatureReport(
82 uint8_t report_id, 80 scoped_refptr<net::IOBuffer> buffer,
83 scoped_refptr<net::IOBufferWithSize> buffer, 81 size_t size,
84 const IOCallback& callback) { 82 const WriteCallback& callback) {
85 WriteReport(kIOHIDReportTypeFeature, report_id, buffer, callback); 83 WriteReport(kIOHIDReportTypeFeature, buffer, size, callback);
86 } 84 }
87 85
88 void HidConnectionMac::InputReportCallback(void* context, 86 void HidConnectionMac::InputReportCallback(void* context,
89 IOReturn result, 87 IOReturn result,
90 void* sender, 88 void* sender,
91 IOHIDReportType type, 89 IOHIDReportType type,
92 uint32_t report_id, 90 uint32_t report_id,
93 uint8_t* report_bytes, 91 uint8_t* report_bytes,
94 CFIndex report_length) { 92 CFIndex report_length) {
95 HidConnectionMac* connection = static_cast<HidConnectionMac*>(context); 93 HidConnectionMac* connection = static_cast<HidConnectionMac*>(context);
96 // report_id is already contained in report_bytes
97 scoped_refptr<net::IOBufferWithSize> buffer; 94 scoped_refptr<net::IOBufferWithSize> buffer;
98 buffer = new net::IOBufferWithSize(report_length); 95 if (connection->device_info().has_report_id) {
99 memcpy(buffer->data(), report_bytes, report_length); 96 // report_id is already contained in report_bytes
97 buffer = new net::IOBufferWithSize(report_length);
98 memcpy(buffer->data(), report_bytes, report_length);
99 } else {
100 buffer = new net::IOBufferWithSize(report_length + 1);
101 buffer->data()[0] = 0;
102 memcpy(buffer->data() + 1, report_bytes, report_length);
103 }
100 104
101 connection->message_loop_->PostTask( 105 connection->message_loop_->PostTask(
102 FROM_HERE, 106 FROM_HERE,
103 base::Bind(&HidConnectionMac::ProcessInputReport, connection, buffer)); 107 base::Bind(&HidConnectionMac::ProcessInputReport, connection, buffer));
104 } 108 }
105 109
106 void HidConnectionMac::WriteReport(IOHIDReportType type, 110 void HidConnectionMac::WriteReport(IOHIDReportType type,
107 uint8_t report_id, 111 scoped_refptr<net::IOBuffer> buffer,
108 scoped_refptr<net::IOBufferWithSize> buffer, 112 size_t size,
109 const IOCallback& callback) { 113 const WriteCallback& callback) {
110 if (!device_) { 114 if (!device_) {
111 callback.Run(false, 0); 115 callback.Run(false);
112 return; 116 return;
113 } 117 }
114 118
115 scoped_refptr<net::IOBufferWithSize> output_buffer; 119 uint8_t* data = reinterpret_cast<uint8_t*>(buffer->data());
116 if (report_id != 0) { 120 DCHECK(size >= 1);
117 output_buffer = new net::IOBufferWithSize(buffer->size() + 1); 121 uint8_t report_id = data[0];
118 output_buffer->data()[0] = static_cast<uint8_t>(report_id); 122 if (report_id == 0) {
119 memcpy(output_buffer->data() + 1, buffer->data(), buffer->size()); 123 // OS X only expects the first byte of the buffer to be the report ID if the
124 // report ID is non-zero.
125 ++data;
126 --size;
127 }
128
129 IOReturn res =
130 IOHIDDeviceSetReport(device_.get(), type, report_id, data, size);
131 if (res == kIOReturnSuccess) {
132 callback.Run(true);
120 } else { 133 } else {
121 output_buffer = new net::IOBufferWithSize(buffer->size()); 134 callback.Run(false);
122 memcpy(output_buffer->data(), buffer->data(), buffer->size());
123 }
124 IOReturn res =
125 IOHIDDeviceSetReport(device_.get(),
126 type,
127 report_id,
128 reinterpret_cast<uint8_t*>(output_buffer->data()),
129 output_buffer->size());
130 if (res != kIOReturnSuccess) {
131 callback.Run(false, 0);
132 } else {
133 callback.Run(true, output_buffer->size());
134 } 135 }
135 } 136 }
136 137
137 void HidConnectionMac::Flush() { 138 void HidConnectionMac::Flush() {
138 while (!pending_reads_.empty()) { 139 while (!pending_reads_.empty()) {
139 pending_reads_.front().callback.Run(false, 0); 140 pending_reads_.front().callback.Run(false, NULL, 0);
140 pending_reads_.pop(); 141 pending_reads_.pop();
141 } 142 }
142 } 143 }
143 144
144 void HidConnectionMac::ProcessInputReport( 145 void HidConnectionMac::ProcessInputReport(
145 scoped_refptr<net::IOBufferWithSize> buffer) { 146 scoped_refptr<net::IOBufferWithSize> buffer) {
146 DCHECK(thread_checker().CalledOnValidThread()); 147 DCHECK(thread_checker().CalledOnValidThread());
147 PendingHidReport report; 148 PendingHidReport report;
148 report.buffer = buffer; 149 report.buffer = buffer;
150 report.size = buffer->size();
149 pending_reports_.push(report); 151 pending_reports_.push(report);
150 ProcessReadQueue(); 152 ProcessReadQueue();
151 } 153 }
152 154
153 void HidConnectionMac::ProcessReadQueue() { 155 void HidConnectionMac::ProcessReadQueue() {
154 DCHECK(thread_checker().CalledOnValidThread()); 156 DCHECK(thread_checker().CalledOnValidThread());
155 while (pending_reads_.size() && pending_reports_.size()) { 157 while (pending_reads_.size() && pending_reports_.size()) {
156 PendingHidRead read = pending_reads_.front(); 158 PendingHidRead read = pending_reads_.front();
157 PendingHidReport report = pending_reports_.front(); 159 PendingHidReport report = pending_reports_.front();
158 160
159 if (read.buffer->size() < report.buffer->size()) { 161 pending_reports_.pop();
160 read.callback.Run(false, 0); 162 if (CompleteRead(report.buffer, report.size, read.callback)) {
161 pending_reads_.pop(); 163 pending_reads_.pop();
162 } else {
163 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size());
164 pending_reports_.pop();
165
166 if (CompleteRead(read.buffer, report.buffer->size(), read.callback)) {
167 pending_reads_.pop();
168 }
169 } 164 }
170 } 165 }
171 } 166 }
172 167
173 } // namespace device 168 } // namespace device
OLDNEW
« no previous file with comments | « device/hid/hid_connection_mac.h ('k') | device/hid/hid_connection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698