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

Side by Side Diff: chrome/browser/usb/usb_device.cc

Issue 10972018: Changing USB API buffer ownership. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Don't leak uninitialized memory into caller. Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/usb/usb_device.h" 5 #include "chrome/browser/usb/usb_device.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "base/synchronization/lock.h" 8 #include "base/synchronization/lock.h"
9 #include "chrome/browser/usb/usb_service.h" 9 #include "chrome/browser/usb/usb_service.h"
10 #include "third_party/libusb/libusb.h" 10 #include "third_party/libusb/libusb.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 service_->CloseDevice(this); 108 service_->CloseDevice(this);
109 handle_ = NULL; 109 handle_ = NULL;
110 } 110 }
111 111
112 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) { 112 void UsbDevice::TransferComplete(PlatformUsbTransferHandle handle) {
113 base::AutoLock lock(lock_); 113 base::AutoLock lock(lock_);
114 114
115 // TODO(gdk): Handle device disconnect. 115 // TODO(gdk): Handle device disconnect.
116 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; 116 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed";
117 Transfer* const transfer = &transfers_[handle]; 117 Transfer* const transfer = &transfers_[handle];
118 if (transfer->buffer.get()) { 118
119 transfer->callback.Run(ConvertTransferStatus(handle->status)); 119 // If the transfer is a control transfer we do not expose the control transfer
120 // setup header to the caller, this logic strips off the header from the
121 // buffer before invoking the callback provided with the transfer with it.
122 scoped_refptr<net::IOBuffer> buffer = transfer->buffer;
123 if (transfer->control_transfer) {
124 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer(
125 handle->actual_length - LIBUSB_CONTROL_SETUP_SIZE);
126 memcpy(resized_buffer->data(), buffer->data() + LIBUSB_CONTROL_SETUP_SIZE,
127 handle->actual_length - LIBUSB_CONTROL_SETUP_SIZE);
128 buffer = resized_buffer;
129 } else {
130 // Clear the remainder of the response buffer. This prevents us from leaking
131 // uninitialized memory into the caller.
132 const size_t remainder = transfer->length - handle->actual_length;
133 memset(buffer->data() + handle->actual_length, 0, remainder);
120 } 134 }
121 135
136 transfer->callback.Run(ConvertTransferStatus(handle->status), buffer,
137 handle->actual_length);
138
122 transfers_.erase(handle); 139 transfers_.erase(handle);
123 libusb_free_transfer(handle); 140 libusb_free_transfer(handle);
124 } 141 }
125 142
126 void UsbDevice::ControlTransfer(const TransferDirection direction, 143 void UsbDevice::ControlTransfer(const TransferDirection direction,
127 const TransferRequestType request_type, const TransferRecipient recipient, 144 const TransferRequestType request_type, const TransferRecipient recipient,
128 const uint8 request, const uint16 value, const uint16 index, 145 const uint8 request, const uint16 value, const uint16 index,
129 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, 146 net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
130 const UsbTransferCallback& callback) { 147 const UsbTransferCallback& callback) {
131 CheckDevice(); 148 CheckDevice();
132 149
150 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
133 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( 151 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize(
134 LIBUSB_CONTROL_SETUP_SIZE + length)); 152 resized_length));
135 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), 153 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
136 length); 154 length);
137 155
138 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 156 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
139 const uint8 converted_type = CreateRequestType(direction, request_type, 157 const uint8 converted_type = CreateRequestType(direction, request_type,
140 recipient); 158 recipient);
141 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), 159 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
142 converted_type, request, value, index, length); 160 converted_type, request, value, index, length);
143 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>( 161 libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(
144 resized_buffer->data()), reinterpret_cast<libusb_transfer_cb_fn>( 162 resized_buffer->data()), reinterpret_cast<libusb_transfer_cb_fn>(
145 &HandleTransferCompletion), this, timeout); 163 &HandleTransferCompletion), this, timeout);
146 SubmitTransfer(transfer, resized_buffer, callback); 164 SubmitTransfer(transfer, true, resized_buffer, resized_length, callback);
147 } 165 }
148 166
149 void UsbDevice::BulkTransfer(const TransferDirection direction, 167 void UsbDevice::BulkTransfer(const TransferDirection direction,
150 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 168 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
151 const unsigned int timeout, const UsbTransferCallback& callback) { 169 const unsigned int timeout, const UsbTransferCallback& callback) {
152 CheckDevice(); 170 CheckDevice();
153 171
154 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 172 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
155 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 173 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
156 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, 174 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint,
157 reinterpret_cast<uint8*>(buffer->data()), length, 175 reinterpret_cast<uint8*>(buffer->data()), length,
158 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, 176 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this,
159 timeout); 177 timeout);
160 SubmitTransfer(transfer, buffer, callback); 178 SubmitTransfer(transfer, false, buffer, length, callback);
161 } 179 }
162 180
163 void UsbDevice::InterruptTransfer(const TransferDirection direction, 181 void UsbDevice::InterruptTransfer(const TransferDirection direction,
164 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 182 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
165 const unsigned int timeout, const UsbTransferCallback& callback) { 183 const unsigned int timeout, const UsbTransferCallback& callback) {
166 CheckDevice(); 184 CheckDevice();
167 185
168 struct libusb_transfer* const transfer = libusb_alloc_transfer(0); 186 struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
169 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 187 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
170 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, 188 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint,
171 reinterpret_cast<uint8*>(buffer->data()), length, 189 reinterpret_cast<uint8*>(buffer->data()), length,
172 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, 190 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this,
173 timeout); 191 timeout);
174 SubmitTransfer(transfer, buffer, callback); 192 SubmitTransfer(transfer, false, buffer, length, callback);
175 } 193 }
176 194
177 void UsbDevice::IsochronousTransfer(const TransferDirection direction, 195 void UsbDevice::IsochronousTransfer(const TransferDirection direction,
178 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, 196 const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
179 const unsigned int packets, const unsigned int packet_length, 197 const unsigned int packets, const unsigned int packet_length,
180 const unsigned int timeout, const UsbTransferCallback& callback) { 198 const unsigned int timeout, const UsbTransferCallback& callback) {
181 CheckDevice(); 199 CheckDevice();
182 200
183 const uint64 total_length = packets * packet_length; 201 const uint64 total_length = packets * packet_length;
184 if (total_length > length) { 202 if (total_length > length) {
185 callback.Run(USB_TRANSFER_LENGTH_SHORT); 203 callback.Run(USB_TRANSFER_LENGTH_SHORT, NULL, 0);
186 return; 204 return;
187 } 205 }
188 206
189 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets); 207 struct libusb_transfer* const transfer = libusb_alloc_transfer(packets);
190 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 208 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
191 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, 209 libusb_fill_iso_transfer(transfer, handle_, new_endpoint,
192 reinterpret_cast<uint8*>(buffer->data()), length, packets, 210 reinterpret_cast<uint8*>(buffer->data()), length, packets,
193 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this, 211 reinterpret_cast<libusb_transfer_cb_fn>(&HandleTransferCompletion), this,
194 timeout); 212 timeout);
195 libusb_set_iso_packet_lengths(transfer, packet_length); 213 libusb_set_iso_packet_lengths(transfer, packet_length);
196 214
197 SubmitTransfer(transfer, buffer, callback); 215 SubmitTransfer(transfer, false, buffer, length, callback);
198 } 216 }
199 217
200 void UsbDevice::CheckDevice() { 218 void UsbDevice::CheckDevice() {
201 DCHECK(handle_) << "Device is already closed."; 219 DCHECK(handle_) << "Device is already closed.";
202 } 220 }
203 221
204 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle, 222 void UsbDevice::SubmitTransfer(PlatformUsbTransferHandle handle,
223 bool control_transfer,
205 net::IOBuffer* buffer, 224 net::IOBuffer* buffer,
225 const size_t length,
206 const UsbTransferCallback& callback) { 226 const UsbTransferCallback& callback) {
207 libusb_submit_transfer(handle);
208
209 Transfer transfer; 227 Transfer transfer;
228 transfer.control_transfer = control_transfer;
210 transfer.buffer = buffer; 229 transfer.buffer = buffer;
230 transfer.length = length;
211 transfer.callback = callback; 231 transfer.callback = callback;
212 232
213 { 233 {
214 base::AutoLock lock(lock_); 234 base::AutoLock lock(lock_);
215 transfers_[handle] = transfer; 235 transfers_[handle] = transfer;
236 libusb_submit_transfer(handle);
216 } 237 }
217 } 238 }
OLDNEW
« chrome/browser/usb/usb_device.h ('K') | « chrome/browser/usb/usb_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698