15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright (c) 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/hid/hid_connection_linux.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <errno.h> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <fcntl.h> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <libudev.h> 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <linux/hidraw.h> 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/ioctl.h> 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file_path.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/posix/eintr_wrapper.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/tuple.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/hid/hid_service.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// These are already defined in newer versions of linux/hidraw.h. 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef HIDIOCSFEATURE 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x06, len) 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef HIDIOCGFEATURE 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x07, len) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace device { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string dev_node) 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : HidConnection(device_info) { 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int flags = base::File::FLAG_OPEN | 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_READ | 37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::File::FLAG_WRITE; 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File device_file(base::FilePath(dev_node), flags); 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!device_file.IsValid()) { 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::File::Error file_error = device_file.error_details(); 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) VLOG(1) << "Access denied opening device read-write, trying read-only."; 456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) device_file = base::File(base::FilePath(dev_node), flags); 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!device_file.IsValid()) { 526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) LOG(ERROR) << "Failed to open '" << dev_node << "': " 536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) << base::File::ErrorToString(device_file.error_details()); 546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (fcntl(device_file.GetPlatformFile(), F_SETFL, 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fcntl(device_file.GetPlatformFile(), F_GETFL) | O_NONBLOCK)) { 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PLOG(ERROR) << "Failed to set non-blocking flag to device file"; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_file_ = device_file.Pass(); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_file_.GetPlatformFile(), 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForIO::WATCH_READ_WRITE, 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &device_file_watcher_, 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this)) { 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Failed to start watching device file."; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidConnectionLinux::~HidConnectionLinux() { 751675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch} 761675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch 771675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdochvoid HidConnectionLinux::PlatformClose() { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Disconnect(); 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Flush(); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HidConnectionLinux::PlatformRead(const ReadCallback& callback) { 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidRead pending_read; 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_read.callback = callback; 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_reads_.push(pending_read); 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProcessReadQueue(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HidConnectionLinux::PlatformWrite(scoped_refptr<net::IOBuffer> buffer, 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t size, 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const WriteCallback& callback) { 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Linux expects the first byte of the buffer to always be a report ID so the 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // buffer can be used directly. 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ssize_t bytes_written = 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HANDLE_EINTR(write(device_file_.GetPlatformFile(), buffer->data(), size)); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bytes_written < 0) { 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Write failed"; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Disconnect(); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(false); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (static_cast<size_t>(bytes_written) != size) { 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOG(WARNING) << "Incomplete HID write: " << bytes_written 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " != " << size; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(true); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformGetFeatureReport( 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8_t report_id, 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ReadCallback& callback) { 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The first byte of the destination buffer is the report ID being requested 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // and is overwritten by the feature report. 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_GT(device_info().max_feature_report_size, 0); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBufferWithSize> buffer( 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new net::IOBufferWithSize(device_info().max_feature_report_size)); 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data()[0] = report_id; 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = ioctl(device_file_.GetPlatformFile(), 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HIDIOCGFEATURE(buffer->size()), 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data()); 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result < 0) { 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Failed to get feature report"; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(false, NULL, 0); 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(true, buffer, result); 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformSendFeatureReport( 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBuffer> buffer, 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t size, 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const WriteCallback& callback) { 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Linux expects the first byte of the buffer to always be a report ID so the 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // buffer can be used directly. 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int result = ioctl( 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device_file_.GetPlatformFile(), HIDIOCSFEATURE(size), buffer->data()); 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result < 0) { 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Failed to send feature report"; 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(false); 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(true); 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::OnFileCanReadWithoutBlocking(int fd) { 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(fd, device_file_.GetPlatformFile()); 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t expected_report_size = device_info().max_input_report_size + 1; 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(expected_report_size)); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char* data = buffer->data(); 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device_info().has_report_id) { 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Linux will not prefix the buffer with a report ID if they are not used 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // by the device. 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data[0] = 0; 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data++; 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci expected_report_size--; 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ssize_t bytes_read = HANDLE_EINTR( 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci read(device_file_.GetPlatformFile(), data, expected_report_size)); 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (bytes_read < 0) { 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (errno == EAGAIN) { 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Read failed"; 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Disconnect(); 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device_info().has_report_id) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Include the byte prepended earlier. 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bytes_read++; 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProcessInputReport(buffer, bytes_read); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) { 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::Disconnect() { 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_file_watcher_.StopWatchingFileDescriptor(); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_file_.Close(); 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Flush(); 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::Flush() { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (!pending_reads_.empty()) { 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_reads_.front().callback.Run(false, NULL, 0); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.pop(); 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HidConnectionLinux::ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t size) { 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PendingHidReport report; 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch report.buffer = buffer; 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci report.size = size; 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reports_.push(report); 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProcessReadQueue(); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HidConnectionLinux::ProcessReadQueue() { 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (pending_reads_.size() && pending_reports_.size()) { 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidRead read = pending_reads_.front(); 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidReport report = pending_reports_.front(); 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_reports_.pop(); 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (CompleteRead(report.buffer, report.size, read.callback)) { 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.pop(); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace device 221