hid_connection_linux.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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)namespace { 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copies a buffer into a new one with a report ID byte inserted at the front. 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<net::IOBufferWithSize> CopyBufferWithReportId( 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::IOBufferWithSize> buffer, 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8_t report_id) { 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::IOBufferWithSize> new_buffer( 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new net::IOBufferWithSize(buffer->size() + 1)); 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new_buffer->data()[0] = report_id; 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(new_buffer->data() + 1, buffer->data(), buffer->size()); 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new_buffer; 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string dev_node) 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : HidConnection(device_info) { 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int flags = base::File::FLAG_OPEN | 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_READ | 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::File::FLAG_WRITE; 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File device_file(base::FilePath(dev_node), flags); 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!device_file.IsValid()) { 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::File::Error file_error = device_file.error_details(); 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { 596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) VLOG(1) << "Access denied opening device read-write, trying read-only."; 606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) device_file = base::File(base::FilePath(dev_node), flags); 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!device_file.IsValid()) { 676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) LOG(ERROR) << "Failed to open '" << dev_node << "': " 686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) << base::File::ErrorToString(device_file.error_details()); 696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (fcntl(device_file.GetPlatformFile(), F_SETFL, 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fcntl(device_file.GetPlatformFile(), F_GETFL) | O_NONBLOCK)) { 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PLOG(ERROR) << "Failed to set non-blocking flag to device file"; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_file_ = device_file.Pass(); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_file_.GetPlatformFile(), 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForIO::WATCH_READ_WRITE, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &device_file_watcher_, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this)) { 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Failed to start watching device file."; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HidConnectionLinux::~HidConnectionLinux() { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Disconnect(); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Flush(); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformRead( 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<net::IOBufferWithSize> buffer, 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IOCallback& callback) { 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidRead pending_read; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_read.buffer = buffer; 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_read.callback = callback; 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_reads_.push(pending_read); 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProcessReadQueue(); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformWrite( 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint8_t report_id, 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<net::IOBufferWithSize> buffer, 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IOCallback& callback) { 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Linux always expects the first byte of the buffer to be the report ID. 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer = CopyBufferWithReportId(buffer, report_id); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int bytes_written = HANDLE_EINTR( 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write(device_file_.GetPlatformFile(), buffer->data(), buffer->size())); 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bytes_written < 0) { 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Write failed"; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Disconnect(); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false, 0); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (bytes_written != buffer->size()) { 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(WARNING) << "Incomplete HID write: " 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << bytes_written << " != " << buffer->size(); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(true, bytes_written == 0 ? 0 : bytes_written - 1); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformGetFeatureReport( 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8_t report_id, 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::IOBufferWithSize> buffer, 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const IOCallback& callback) { 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (buffer->size() == 0) { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false, 0); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The first byte of the destination buffer is the report ID being requested. 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data()[0] = report_id; 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = ioctl(device_file_.GetPlatformFile(), 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HIDIOCGFEATURE(buffer->size()), 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data()); 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result < 0) { 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Failed to get feature report"; 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(false, 0); 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(true, result); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::PlatformSendFeatureReport( 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8_t report_id, 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::IOBufferWithSize> buffer, 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const IOCallback& callback) { 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (report_id != 0) 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer = CopyBufferWithReportId(buffer, report_id); 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = ioctl(device_file_.GetPlatformFile(), 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HIDIOCSFEATURE(buffer->size()), 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data()); 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result < 0) { 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Failed to send feature report"; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false, 0); 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(true, result); 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::OnFileCanReadWithoutBlocking(int fd) { 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(fd, device_file_.GetPlatformFile()); 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint8 raw_buffer[1024] = {0}; 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int bytes_read = 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HANDLE_EINTR(read(device_file_.GetPlatformFile(), raw_buffer, 1024)); 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (bytes_read < 0) { 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (errno == EAGAIN) { 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VPLOG(1) << "Read failed"; 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Disconnect(); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<net::IOBufferWithSize> buffer = 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new net::IOBufferWithSize(bytes_read); 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memcpy(buffer->data(), raw_buffer, bytes_read); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProcessInputReport(buffer); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) { 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::Disconnect() { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_file_watcher_.StopWatchingFileDescriptor(); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_file_.Close(); 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Flush(); 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::Flush() { 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (!pending_reads_.empty()) { 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.front().callback.Run(false, 0); 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.pop(); 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HidConnectionLinux::ProcessInputReport( 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<net::IOBufferWithSize> buffer) { 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PendingHidReport report; 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch report.buffer = buffer; 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reports_.push(report); 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProcessReadQueue(); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HidConnectionLinux::ProcessReadQueue() { 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(thread_checker().CalledOnValidThread()); 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (pending_reads_.size() && pending_reports_.size()) { 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidRead read = pending_reads_.front(); 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PendingHidReport report = pending_reports_.front(); 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (read.buffer->size() < report.buffer->size()) { 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read.callback.Run(false, 0); 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.pop(); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_reports_.pop(); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (CompleteRead(report.buffer, read.callback)) { 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_reads_.pop(); 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace device 235