• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2012 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/media/devices/deviceinfo.h"
29 
30 #include "talk/media/devices/libudevsymboltable.h"
31 #include "webrtc/base/common.h"  // for ASSERT
32 
33 namespace cricket {
34 
35 class ScopedLibUdev {
36  public:
Create()37   static ScopedLibUdev* Create() {
38     ScopedLibUdev* ret_val = new ScopedLibUdev();
39     if (!ret_val->Init()) {
40       delete ret_val;
41       return NULL;
42     }
43     return ret_val;
44   }
~ScopedLibUdev()45   ~ScopedLibUdev() {
46     libudev_.Unload();
47   }
48 
instance()49   LibUDevSymbolTable* instance() { return &libudev_; }
50 
51  private:
ScopedLibUdev()52   ScopedLibUdev() {}
53 
Init()54   bool Init() {
55     return libudev_.Load() &&
56            !IsWrongLibUDevAbiVersion(libudev_.GetDllHandle());
57   }
58 
59   LibUDevSymbolTable libudev_;
60 };
61 
62 class ScopedUdev {
63  public:
ScopedUdev(LibUDevSymbolTable * libudev)64   explicit ScopedUdev(LibUDevSymbolTable* libudev) : libudev_(libudev) {
65     udev_ = libudev_->udev_new()();
66   }
~ScopedUdev()67   ~ScopedUdev() {
68     if (udev_) libudev_->udev_unref()(udev_);
69   }
70 
instance()71   udev* instance() { return udev_; }
72 
73  private:
74   LibUDevSymbolTable* libudev_;
75   udev* udev_;
76 };
77 
78 class ScopedUdevEnumerate {
79  public:
ScopedUdevEnumerate(LibUDevSymbolTable * libudev,udev * udev)80   ScopedUdevEnumerate(LibUDevSymbolTable* libudev, udev* udev)
81       : libudev_(libudev) {
82     enumerate_ = libudev_->udev_enumerate_new()(udev);
83   }
~ScopedUdevEnumerate()84   ~ScopedUdevEnumerate() {
85     if (enumerate_) libudev_->udev_enumerate_unref()(enumerate_);
86   }
87 
instance()88   udev_enumerate* instance() { return enumerate_; }
89 
90  private:
91   LibUDevSymbolTable* libudev_;
92   udev_enumerate* enumerate_;
93 };
94 
GetUsbProperty(const Device & device,const char * property_name,std::string * property)95 bool GetUsbProperty(const Device& device, const char* property_name,
96                     std::string* property) {
97   rtc::scoped_ptr<ScopedLibUdev> libudev_context(ScopedLibUdev::Create());
98   if (!libudev_context) {
99     return false;
100   }
101   ScopedUdev udev_context(libudev_context->instance());
102   if (!udev_context.instance()) {
103     return false;
104   }
105   ScopedUdevEnumerate enumerate_context(libudev_context->instance(),
106                                         udev_context.instance());
107   if (!enumerate_context.instance()) {
108     return false;
109   }
110   libudev_context->instance()->udev_enumerate_add_match_subsystem()(
111       enumerate_context.instance(), "video4linux");
112   libudev_context->instance()->udev_enumerate_scan_devices()(
113       enumerate_context.instance());
114   udev_list_entry* devices =
115       libudev_context->instance()->udev_enumerate_get_list_entry()(
116           enumerate_context.instance());
117   if (!devices) {
118     return false;
119   }
120   udev_list_entry* dev_list_entry = NULL;
121   const char* property_value = NULL;
122   // Macro that expands to a for-loop over the devices.
123   for (dev_list_entry = devices; dev_list_entry != NULL;
124        dev_list_entry = libudev_context->instance()->
125            udev_list_entry_get_next()(dev_list_entry)) {
126     const char* path = libudev_context->instance()->udev_list_entry_get_name()(
127         dev_list_entry);
128     if (!path) continue;
129     udev_device* dev =
130         libudev_context->instance()->udev_device_new_from_syspath()(
131             udev_context.instance(), path);
132     if (!dev) continue;
133     const char* device_node =
134         libudev_context->instance()->udev_device_get_devnode()(dev);
135     if (!device_node || device.id.compare(device_node) != 0) {
136       continue;
137     }
138     dev = libudev_context->instance()->
139         udev_device_get_parent_with_subsystem_devtype()(
140             dev, "usb", "usb_device");
141     if (!dev) continue;
142     property_value = libudev_context->instance()->
143         udev_device_get_sysattr_value()(
144             dev, property_name);
145     break;
146   }
147   if (!property_value) {
148     return false;
149   }
150   property->assign(property_value);
151   return true;
152 }
153 
GetUsbId(const Device & device,std::string * usb_id)154 bool GetUsbId(const Device& device, std::string* usb_id) {
155   std::string id_vendor;
156   std::string id_product;
157   if (!GetUsbProperty(device, "idVendor", &id_vendor)) {
158     return false;
159   }
160   if (!GetUsbProperty(device, "idProduct", &id_product)) {
161     return false;
162   }
163   usb_id->clear();
164   usb_id->append(id_vendor);
165   usb_id->append(":");
166   usb_id->append(id_product);
167   return true;
168 }
169 
GetUsbVersion(const Device & device,std::string * usb_version)170 bool GetUsbVersion(const Device& device, std::string* usb_version) {
171   return GetUsbProperty(device, "version", usb_version);
172 }
173 
174 }  // namespace cricket
175