| 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_linux.h" | 5 #include "device/hid/hid_connection_linux.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <libudev.h> | 9 #include <libudev.h> |
| 10 #include <linux/hidraw.h> | 10 #include <linux/hidraw.h> |
| 11 |
| 11 #include <string> | 12 #include <string> |
| 12 | 13 |
| 13 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
| 14 #include "base/tuple.h" | 15 #include "base/tuple.h" |
| 15 #include "device/hid/hid_service.h" | 16 #include "device/hid/hid_service.h" |
| 16 #include "device/hid/hid_service_linux.h" | 17 #include "device/hid/hid_service_linux.h" |
| 17 | 18 |
| 18 | |
| 19 namespace device { | 19 namespace device { |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 const char kHidrawSubsystem[] = "hidraw"; | 23 const char kHidrawSubsystem[] = "hidraw"; |
| 24 | 24 |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, | 27 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, |
| 28 ScopedUdevDevicePtr udev_raw_device) | 28 ScopedUdevDevicePtr udev_raw_device) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 | 87 |
| 88 uint8 buffer[1024] = {0}; | 88 uint8 buffer[1024] = {0}; |
| 89 int bytes = read(device_file_, buffer, 1024); | 89 int bytes = read(device_file_, buffer, 1024); |
| 90 if (bytes < 0) { | 90 if (bytes < 0) { |
| 91 if (errno == EAGAIN) { | 91 if (errno == EAGAIN) { |
| 92 return; | 92 return; |
| 93 } | 93 } |
| 94 Disconnect(); | 94 Disconnect(); |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(bytes)); | 97 |
| 98 memcpy(io_buffer->data(), buffer, bytes); | 98 PendingHidReport report; |
| 99 input_reports_.push(std::make_pair(io_buffer, bytes)); | 99 report.buffer = new net::IOBufferWithSize(bytes); |
| 100 memcpy(report.buffer->data(), buffer, bytes); |
| 101 pending_reports_.push(report); |
| 100 | 102 |
| 101 ProcessReadQueue(); | 103 ProcessReadQueue(); |
| 102 } | 104 } |
| 103 | 105 |
| 104 void HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) {} | 106 void HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) {} |
| 105 | 107 |
| 106 void HidConnectionLinux::Disconnect() { | 108 void HidConnectionLinux::Disconnect() { |
| 107 DCHECK(thread_checker_.CalledOnValidThread()); | 109 DCHECK(thread_checker_.CalledOnValidThread()); |
| 108 if (!initialized_) | 110 if (!initialized_) |
| 109 return; | 111 return; |
| 110 | 112 |
| 111 initialized_ = false; | 113 initialized_ = false; |
| 112 device_file_watcher_.StopWatchingFileDescriptor(); | 114 device_file_watcher_.StopWatchingFileDescriptor(); |
| 113 close(device_file_); | 115 close(device_file_); |
| 114 while (!read_queue_.empty()) { | 116 while (!pending_reads_.empty()) { |
| 115 PendingRequest callback = read_queue_.front(); | 117 PendingHidRead pending_read = pending_reads_.front(); |
| 116 read_queue_.pop(); | 118 pending_reads_.pop(); |
| 117 callback.c.Run(false, 0); | 119 pending_read.callback.Run(false, 0); |
| 118 } | 120 } |
| 119 } | 121 } |
| 120 | 122 |
| 121 void HidConnectionLinux::Read(scoped_refptr<net::IOBuffer> buffer, | 123 void HidConnectionLinux::Read(scoped_refptr<net::IOBufferWithSize> buffer, |
| 122 size_t size, | |
| 123 const IOCallback& callback) { | 124 const IOCallback& callback) { |
| 124 DCHECK(thread_checker_.CalledOnValidThread()); | 125 DCHECK(thread_checker_.CalledOnValidThread()); |
| 126 PendingHidRead pending_read; |
| 127 pending_read.buffer = buffer; |
| 128 pending_read.callback = callback; |
| 125 if (!initialized_) { | 129 if (!initialized_) { |
| 126 DCHECK(read_queue_.empty()); | 130 DCHECK(pending_reads_.empty()); |
| 127 // There might be unread reports. | 131 // There might be unread reports. |
| 128 if (!input_reports_.empty()){ | 132 if (!pending_reports_.empty()) { |
| 129 read_queue_.push(MakeTuple(buffer, size, callback)); | 133 pending_reads_.push(pending_read); |
| 130 ProcessReadQueue(); | 134 ProcessReadQueue(); |
| 131 } | 135 } |
| 132 callback.Run(false, 0); | 136 callback.Run(false, 0); |
| 133 return; | 137 return; |
| 134 } else { | 138 } else { |
| 135 read_queue_.push(MakeTuple(buffer, size, callback)); | 139 pending_reads_.push(pending_read); |
| 136 ProcessReadQueue(); | 140 ProcessReadQueue(); |
| 137 } | 141 } |
| 138 } | 142 } |
| 139 | 143 |
| 140 void HidConnectionLinux::Write(scoped_refptr<net::IOBuffer> buffer, | 144 void HidConnectionLinux::Write(scoped_refptr<net::IOBufferWithSize> buffer, |
| 141 size_t size, | |
| 142 const IOCallback& callback) { | 145 const IOCallback& callback) { |
| 143 DCHECK(thread_checker_.CalledOnValidThread()); | 146 DCHECK(thread_checker_.CalledOnValidThread()); |
| 144 if (!initialized_) { | 147 if (!initialized_) { |
| 145 callback.Run(false, 0); | 148 callback.Run(false, 0); |
| 146 return; | 149 return; |
| 147 } else { | 150 } else { |
| 148 int bytes = write(device_file_, buffer->data(), size); | 151 int bytes = write(device_file_, buffer->data(), buffer->size()); |
| 149 if (bytes < 0) { | 152 if (bytes < 0) { |
| 150 Disconnect(); | 153 Disconnect(); |
| 151 callback.Run(false, 0); | 154 callback.Run(false, 0); |
| 152 } else { | 155 } else { |
| 153 callback.Run(true, bytes); | 156 callback.Run(true, bytes); |
| 154 } | 157 } |
| 155 } | 158 } |
| 156 } | 159 } |
| 157 | 160 |
| 158 void HidConnectionLinux::GetFeatureReport(scoped_refptr<net::IOBuffer> buffer, | 161 void HidConnectionLinux::GetFeatureReport( |
| 159 size_t size, | 162 scoped_refptr<net::IOBufferWithSize> buffer, |
| 160 const IOCallback& callback) { | 163 const IOCallback& callback) { |
| 161 DCHECK(thread_checker_.CalledOnValidThread()); | 164 DCHECK(thread_checker_.CalledOnValidThread()); |
| 162 if (!initialized_) { | 165 if (!initialized_) { |
| 163 callback.Run(false, 0); | 166 callback.Run(false, 0); |
| 164 return; | 167 return; |
| 165 } | 168 } |
| 166 NOTIMPLEMENTED(); | 169 NOTIMPLEMENTED(); |
| 167 } | 170 } |
| 168 | 171 |
| 169 void HidConnectionLinux::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer, | 172 void HidConnectionLinux::SendFeatureReport( |
| 170 size_t size, | 173 scoped_refptr<net::IOBufferWithSize> buffer, |
| 171 const IOCallback& callback) { | 174 const IOCallback& callback) { |
| 172 DCHECK(thread_checker_.CalledOnValidThread()); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
| 173 if (!initialized_) { | 176 if (!initialized_) { |
| 174 callback.Run(false, 0); | 177 callback.Run(false, 0); |
| 175 return; | 178 return; |
| 176 } | 179 } |
| 177 NOTIMPLEMENTED(); | 180 NOTIMPLEMENTED(); |
| 178 } | 181 } |
| 179 | 182 |
| 180 void HidConnectionLinux::ProcessReadQueue() { | 183 void HidConnectionLinux::ProcessReadQueue() { |
| 181 while(read_queue_.size() && input_reports_.size()) { | 184 while (pending_reads_.size() && pending_reports_.size()) { |
| 182 PendingRequest request = read_queue_.front(); | 185 PendingHidRead read = pending_reads_.front(); |
| 183 read_queue_.pop(); | 186 pending_reads_.pop(); |
| 184 PendingReport report = input_reports_.front(); | 187 PendingHidReport report = pending_reports_.front(); |
| 185 if (report.second > request.b) { | 188 if (report.buffer->size() > read.buffer->size()) { |
| 186 request.c.Run(false, report.second); | 189 read.callback.Run(false, report.buffer->size()); |
| 187 } else { | 190 } else { |
| 188 memcpy(request.a->data(), report.first->data(), report.second); | 191 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); |
| 189 input_reports_.pop(); | 192 pending_reports_.pop(); |
| 190 request.c.Run(true, report.second); | 193 read.callback.Run(true, report.buffer->size()); |
| 191 } | 194 } |
| 192 } | 195 } |
| 193 } | 196 } |
| 194 | 197 |
| 195 bool HidConnectionLinux::FindHidrawDevNode(udev_device* parent, | 198 bool HidConnectionLinux::FindHidrawDevNode(udev_device* parent, |
| 196 std::string* result) { | 199 std::string* result) { |
| 197 udev* udev = udev_device_get_udev(parent); | 200 udev* udev = udev_device_get_udev(parent); |
| 198 if (!udev) | 201 if (!udev) |
| 199 return false; | 202 return false; |
| 200 | 203 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 222 raw_path) { | 225 raw_path) { |
| 223 *result = raw_path; | 226 *result = raw_path; |
| 224 return true; | 227 return true; |
| 225 } | 228 } |
| 226 } | 229 } |
| 227 | 230 |
| 228 return false; | 231 return false; |
| 229 } | 232 } |
| 230 | 233 |
| 231 } // namespace device | 234 } // namespace device |
| OLD | NEW |