1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "device/hid/hid_service.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_vector.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/stl_util.h" 12 13 #if defined(OS_LINUX) && defined(USE_UDEV) 14 #include "device/hid/hid_service_linux.h" 15 #elif defined(OS_MACOSX) 16 #include "device/hid/hid_service_mac.h" 17 #else 18 #include "device/hid/hid_service_win.h" 19 #endif 20 21 namespace device { 22 23 namespace { 24 25 HidService* g_service = NULL; 26 27 } // namespace 28 29 class HidService::Destroyer : public base::MessageLoop::DestructionObserver { 30 public: 31 explicit Destroyer(HidService* hid_service) 32 : hid_service_(hid_service) {} 33 virtual ~Destroyer() {} 34 35 private: 36 // base::MessageLoop::DestructionObserver implementation. 37 virtual void WillDestroyCurrentMessageLoop() OVERRIDE { 38 base::MessageLoop::current()->RemoveDestructionObserver(this); 39 delete hid_service_; 40 delete this; 41 g_service = NULL; 42 } 43 44 HidService* hid_service_; 45 }; 46 47 HidService* HidService::GetInstance( 48 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, 49 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { 50 if (g_service == NULL) { 51 #if defined(OS_LINUX) && defined(USE_UDEV) 52 g_service = new HidServiceLinux(ui_task_runner); 53 #elif defined(OS_MACOSX) 54 g_service = new HidServiceMac(file_task_runner); 55 #elif defined(OS_WIN) 56 g_service = new HidServiceWin(); 57 #endif 58 if (g_service != NULL) { 59 Destroyer* destroyer = new Destroyer(g_service); 60 base::MessageLoop::current()->AddDestructionObserver(destroyer); 61 } 62 } 63 return g_service; 64 } 65 66 HidService::~HidService() { 67 DCHECK(thread_checker_.CalledOnValidThread()); 68 } 69 70 void HidService::GetDevices(std::vector<HidDeviceInfo>* devices) { 71 DCHECK(thread_checker_.CalledOnValidThread()); 72 STLClearObject(devices); 73 for (DeviceMap::iterator it = devices_.begin(); 74 it != devices_.end(); 75 ++it) { 76 devices->push_back(it->second); 77 } 78 } 79 80 // Fills in the device info struct of the given device_id. 81 bool HidService::GetDeviceInfo(const HidDeviceId& device_id, 82 HidDeviceInfo* info) const { 83 DeviceMap::const_iterator it = devices_.find(device_id); 84 if (it == devices_.end()) 85 return false; 86 *info = it->second; 87 return true; 88 } 89 90 HidService::HidService() { 91 DCHECK(thread_checker_.CalledOnValidThread()); 92 } 93 94 void HidService::AddDevice(const HidDeviceInfo& info) { 95 DCHECK(thread_checker_.CalledOnValidThread()); 96 if (!ContainsKey(devices_, info.device_id)) { 97 devices_[info.device_id] = info; 98 } 99 } 100 101 void HidService::RemoveDevice(const HidDeviceId& device_id) { 102 DCHECK(thread_checker_.CalledOnValidThread()); 103 DeviceMap::iterator it = devices_.find(device_id); 104 if (it != devices_.end()) 105 devices_.erase(it); 106 } 107 108 } // namespace device 109