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

Side by Side Diff: chrome/browser/usb/usb_device_handle.h

Issue 22492003: Fixes leaking transfer objects due to improper USB handle closure. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 #ifndef CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_ 5 #ifndef CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
6 #define CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_ 6 #define CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
7 7
8 #include <map> 8 #include <map>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
13 #include "base/synchronization/lock.h" 13 #include "base/synchronization/lock.h"
14 #include "base/threading/thread_checker.h" 14 #include "base/threading/thread_checker.h"
15 #include "chrome/browser/usb/usb_interface.h" 15 #include "chrome/browser/usb/usb_interface.h"
16 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 #include "net/base/completion_callback.h" 17 #include "net/base/completion_callback.h"
18 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
19 19
20 struct libusb_device_handle; 20 struct libusb_device_handle;
21 struct libusb_iso_packet_descriptor; 21 struct libusb_iso_packet_descriptor;
22 struct libusb_transfer; 22 struct libusb_transfer;
23 23
24 typedef libusb_device_handle* PlatformUsbDeviceHandle; 24 typedef libusb_device_handle* PlatformUsbDeviceHandle;
25 typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor; 25 typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor;
26 typedef libusb_transfer* PlatformUsbTransferHandle; 26 typedef libusb_transfer* PlatformUsbTransferHandle;
27 27
28 class UsbContext;
29 class UsbConfigDescriptor;
28 class UsbDevice; 30 class UsbDevice;
31 class UsbInterface;
29 32
30 namespace net { 33 namespace net {
31 class IOBuffer; 34 class IOBuffer;
32 } // namespace net 35 } // namespace net
33 36
34 enum UsbTransferStatus { 37 enum UsbTransferStatus {
35 USB_TRANSFER_COMPLETED = 0, 38 USB_TRANSFER_COMPLETED = 0,
36 USB_TRANSFER_ERROR, 39 USB_TRANSFER_ERROR,
37 USB_TRANSFER_TIMEOUT, 40 USB_TRANSFER_TIMEOUT,
38 USB_TRANSFER_CANCELLED, 41 USB_TRANSFER_CANCELLED,
39 USB_TRANSFER_STALLED, 42 USB_TRANSFER_STALLED,
40 USB_TRANSFER_DISCONNECT, 43 USB_TRANSFER_DISCONNECT,
41 USB_TRANSFER_OVERFLOW, 44 USB_TRANSFER_OVERFLOW,
42 USB_TRANSFER_LENGTH_SHORT, 45 USB_TRANSFER_LENGTH_SHORT,
43 }; 46 };
44 47
45 typedef base::Callback<void(UsbTransferStatus, scoped_refptr<net::IOBuffer>, 48 typedef base::Callback<void(UsbTransferStatus, scoped_refptr<net::IOBuffer>,
46 size_t)> UsbTransferCallback; 49 size_t)> UsbTransferCallback;
47 50
48 // UsbDeviceHandle class provides basic I/O related functionalities. 51 // UsbDeviceHandle class provides basic I/O related functionalities.
49 class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> { 52 class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
50 public: 53 public:
51 enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED }; 54 enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
52 enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER }; 55 enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
53 56
54 scoped_refptr<UsbDevice> device() const; 57 scoped_refptr<UsbDevice> device() const;
55 PlatformUsbDeviceHandle handle() const { return handle_; } 58 PlatformUsbDeviceHandle handle() const { return handle_; }
56 59
57 // Close the USB device and release the underlying platform device. 60 // Notifies UsbDevice to drop the reference of this object; cancels all the
61 // flying transfers.
62 // It is possible that the object has no other reference after this call. So
63 // if it is called using a raw pointer, it could be invalidated.
64 // The platform device handle will be closed when UsbDeviceHandle destructs.
58 virtual void Close(); 65 virtual void Close();
59 66
60 // Device manipulation operations. These methods are blocking and must be 67 // Device manipulation operations. These methods are blocking and must be
61 // called on FILE thread. 68 // called on FILE thread.
62 virtual bool ClaimInterface(const int interface_number); 69 virtual bool ClaimInterface(const int interface_number);
63 virtual bool ReleaseInterface(const int interface_number); 70 virtual bool ReleaseInterface(const int interface_number);
64 virtual bool SetInterfaceAlternateSetting( 71 virtual bool SetInterfaceAlternateSetting(
65 const int interface_number, 72 const int interface_number,
66 const int alternate_setting); 73 const int alternate_setting);
67 virtual bool ResetDevice(); 74 virtual bool ResetDevice();
68 bool GetSerial(base::string16* serial); 75 virtual bool GetSerial(base::string16* serial);
69 76
70 // Async IO. Can be called on any thread. 77 // Async IO. Can be called on any thread.
71 virtual void ControlTransfer(const UsbEndpointDirection direction, 78 virtual void ControlTransfer(const UsbEndpointDirection direction,
72 const TransferRequestType request_type, 79 const TransferRequestType request_type,
73 const TransferRecipient recipient, 80 const TransferRecipient recipient,
74 const uint8 request, 81 const uint8 request,
75 const uint16 value, 82 const uint16 value,
76 const uint16 index, 83 const uint16 index,
77 net::IOBuffer* buffer, 84 net::IOBuffer* buffer,
78 const size_t length, 85 const size_t length,
(...skipping 16 matching lines...) Expand all
95 102
96 virtual void IsochronousTransfer(const UsbEndpointDirection direction, 103 virtual void IsochronousTransfer(const UsbEndpointDirection direction,
97 const uint8 endpoint, 104 const uint8 endpoint,
98 net::IOBuffer* buffer, 105 net::IOBuffer* buffer,
99 const size_t length, 106 const size_t length,
100 const unsigned int packets, 107 const unsigned int packets,
101 const unsigned int packet_length, 108 const unsigned int packet_length,
102 const unsigned int timeout, 109 const unsigned int timeout,
103 const UsbTransferCallback& callback); 110 const UsbTransferCallback& callback);
104 111
105 // Normal code should not call this function. It is called by the platform's
106 // callback mechanism in such a way that it cannot be made private. Invokes
107 // the callbacks associated with a given transfer, and removes it from the
108 // in-flight transfer set.
109 void TransferComplete(PlatformUsbTransferHandle transfer);
110
111 protected: 112 protected:
112 friend class base::RefCountedThreadSafe<UsbDeviceHandle>; 113 friend class base::RefCountedThreadSafe<UsbDeviceHandle>;
113 friend class UsbDevice; 114 friend class UsbDevice;
114 115
115 // This constructor is called by UsbDevice. 116 // This constructor is called by UsbDevice.
116 UsbDeviceHandle(UsbDevice* device, PlatformUsbDeviceHandle handle); 117 UsbDeviceHandle(scoped_refptr<UsbContext> context,
118 UsbDevice* device, PlatformUsbDeviceHandle handle);
117 119
118 // This constructor variant is for use in testing only. 120 // This constructor variant is for use in testing only.
119 UsbDeviceHandle(); 121 UsbDeviceHandle();
120 virtual ~UsbDeviceHandle(); 122 virtual ~UsbDeviceHandle();
121 123
122 UsbDevice* device_; 124 UsbDevice* device_;
123 125
124 private: 126 private:
127 friend void HandleTransferCompletion(PlatformUsbTransferHandle handle);
pfeldman 2013/08/09 08:58:59 This can be defined in .cc
Bei Zhang 2013/08/09 16:43:55 How would you do that?
128
129 class InterfaceClaimer : public base::RefCountedThreadSafe<InterfaceClaimer> {
pfeldman 2013/08/09 08:58:59 No need for it for be ref-counted. You can store i
Bei Zhang 2013/08/09 16:43:55 It will be shared, by both UsbDeviceHandle and Tra
130 public:
131 InterfaceClaimer(const PlatformUsbDeviceHandle handle,
132 const int interface_number);
133 int alternate_setting() const { return alternate_setting_; }
134 void set_alternate_setting(const int alternate_setting) {
135 alternate_setting_ = alternate_setting;
136 }
137
138 private:
139 friend class UsbDevice;
140 friend class base::RefCountedThreadSafe<InterfaceClaimer>;
141 ~InterfaceClaimer();
142
143 const PlatformUsbDeviceHandle handle_;
144 const int interface_number_;
145 int alternate_setting_;
146
147 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
148 };
149
125 struct Transfer { 150 struct Transfer {
126 Transfer(); 151 Transfer();
127 ~Transfer(); 152 ~Transfer();
128 153
129 UsbTransferType transfer_type; 154 UsbTransferType transfer_type;
130 scoped_refptr<net::IOBuffer> buffer; 155 scoped_refptr<net::IOBuffer> buffer;
156 scoped_refptr<InterfaceClaimer> claimed_interface;
131 size_t length; 157 size_t length;
132 UsbTransferCallback callback; 158 UsbTransferCallback callback;
133 }; 159 };
134 160
161 // Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
162 // SetInterfaceAlternateSetting.
163 void RefreshEndpointMap();
164
135 // Submits a transfer and starts tracking it. Retains the buffer and copies 165 // Submits a transfer and starts tracking it. Retains the buffer and copies
136 // the completion callback until the transfer finishes, whereupon it invokes 166 // the completion callback until the transfer finishes, whereupon it invokes
137 // the callback then releases the buffer. 167 // the callback then releases the buffer.
138 void SubmitTransfer(PlatformUsbTransferHandle handle, 168 void SubmitTransfer(PlatformUsbTransferHandle handle,
139 UsbTransferType transfer_type, 169 UsbTransferType transfer_type,
140 net::IOBuffer* buffer, 170 net::IOBuffer* buffer,
141 const size_t length, 171 const size_t length,
142 const UsbTransferCallback& callback); 172 const UsbTransferCallback& callback);
143 173
144 // Close the current device handle without inform the corresponding UsbDevice. 174 // Normal code should not call this function. It is called by the platform's
175 // callback mechanism in such a way that it cannot be made private. Invokes
pfeldman 2013/08/09 08:58:59 It can now be private (and is such), fix the comme
Bei Zhang 2013/08/09 16:43:55 Done.
176 // the callbacks associated with a given transfer, and removes it from the
177 // in-flight transfer set.
178 void TransferComplete(PlatformUsbTransferHandle transfer);
179
180 // Closes the current device handle without inform the corresponding
181 // UsbDevice.
145 void InternalClose(); 182 void InternalClose();
146 183
147 PlatformUsbDeviceHandle handle_; 184 PlatformUsbDeviceHandle handle_;
148 185
149 // transfers_ tracks all in-flight transfers associated with this device, 186 scoped_refptr<UsbConfigDescriptor> interfaces_;
150 // allowing the device to retain the buffer and callback associated with a 187
151 // transfer until such time that it completes. It is protected by lock_. 188 typedef std::map<int, scoped_refptr<InterfaceClaimer> > ClaimedInterfaceMap;
152 base::Lock lock_; 189 ClaimedInterfaceMap claimed_interfaces_;
153 std::map<PlatformUsbTransferHandle, Transfer> transfers_; 190
191 typedef std::map<PlatformUsbTransferHandle, Transfer> TransferMap;
192 TransferMap transfers_;
193
194 // A map from endpoints to interfaces
195 typedef std::map<int, int> EndpointMap;
196 EndpointMap endpoint_map_;
197
198 // Retain the UsbContext so that the platform context will not be destroyed
199 // before this handle.
200 scoped_refptr<UsbContext> context_;
154 201
155 base::ThreadChecker thread_checker_; 202 base::ThreadChecker thread_checker_;
156 203
157 DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle); 204 DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
158 }; 205 };
159 206
160 #endif // CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_ 207 #endif // CHROME_BROWSER_USB_USB_DEVICE_HANDLE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698