blob: 7b5200112c6a0c50f0ca092703757d2237b32e01 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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/base/common.h" // for ASSERT
31#include "talk/media/devices/libudevsymboltable.h"
32
33namespace cricket {
34
35class ScopedLibUdev {
36 public:
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 }
45 ~ScopedLibUdev() {
46 libudev_.Unload();
47 }
48
49 LibUDevSymbolTable* instance() { return &libudev_; }
50
51 private:
52 ScopedLibUdev() {}
53
54 bool Init() {
55 return libudev_.Load();
56 }
57
58 LibUDevSymbolTable libudev_;
59};
60
61class ScopedUdev {
62 public:
63 explicit ScopedUdev(LibUDevSymbolTable* libudev) : libudev_(libudev) {
64 udev_ = libudev_->udev_new()();
65 }
66 ~ScopedUdev() {
67 if (udev_) libudev_->udev_unref()(udev_);
68 }
69
70 udev* instance() { return udev_; }
71
72 private:
73 LibUDevSymbolTable* libudev_;
74 udev* udev_;
75};
76
77class ScopedUdevEnumerate {
78 public:
79 ScopedUdevEnumerate(LibUDevSymbolTable* libudev, udev* udev)
80 : libudev_(libudev) {
81 enumerate_ = libudev_->udev_enumerate_new()(udev);
82 }
83 ~ScopedUdevEnumerate() {
84 if (enumerate_) libudev_->udev_enumerate_unref()(enumerate_);
85 }
86
87 udev_enumerate* instance() { return enumerate_; }
88
89 private:
90 LibUDevSymbolTable* libudev_;
91 udev_enumerate* enumerate_;
92};
93
94bool GetUsbProperty(const Device& device, const char* property_name,
95 std::string* property) {
96 talk_base::scoped_ptr<ScopedLibUdev> libudev_context(ScopedLibUdev::Create());
97 if (!libudev_context) {
98 return false;
99 }
100 ScopedUdev udev_context(libudev_context->instance());
101 if (!udev_context.instance()) {
102 return false;
103 }
104 ScopedUdevEnumerate enumerate_context(libudev_context->instance(),
105 udev_context.instance());
106 if (!enumerate_context.instance()) {
107 return false;
108 }
109 libudev_context->instance()->udev_enumerate_add_match_subsystem()(
110 enumerate_context.instance(), "video4linux");
111 libudev_context->instance()->udev_enumerate_scan_devices()(
112 enumerate_context.instance());
113 udev_list_entry* devices =
114 libudev_context->instance()->udev_enumerate_get_list_entry()(
115 enumerate_context.instance());
116 if (!devices) {
117 return false;
118 }
119 udev_list_entry* dev_list_entry = NULL;
120 const char* property_value = NULL;
121 // Macro that expands to a for-loop over the devices.
122 for (dev_list_entry = devices; dev_list_entry != NULL;
123 dev_list_entry = libudev_context->instance()->
124 udev_list_entry_get_next()(dev_list_entry)) {
125 const char* path = libudev_context->instance()->udev_list_entry_get_name()(
126 dev_list_entry);
127 if (!path) continue;
128 udev_device* dev =
129 libudev_context->instance()->udev_device_new_from_syspath()(
130 udev_context.instance(), path);
131 if (!dev) continue;
132 const char* device_node =
133 libudev_context->instance()->udev_device_get_devnode()(dev);
134 if (!device_node || device.id.compare(device_node) != 0) {
135 continue;
136 }
137 dev = libudev_context->instance()->
138 udev_device_get_parent_with_subsystem_devtype()(
139 dev, "usb", "usb_device");
140 if (!dev) continue;
141 property_value = libudev_context->instance()->
142 udev_device_get_sysattr_value()(
143 dev, property_name);
144 break;
145 }
146 if (!property_value) {
147 return false;
148 }
149 property->assign(property_value);
150 return true;
151}
152
153bool GetUsbId(const Device& device, std::string* usb_id) {
154 std::string id_vendor;
155 std::string id_product;
156 if (!GetUsbProperty(device, "idVendor", &id_vendor)) {
157 return false;
158 }
159 if (!GetUsbProperty(device, "idProduct", &id_product)) {
160 return false;
161 }
162 usb_id->clear();
163 usb_id->append(id_vendor);
164 usb_id->append(":");
165 usb_id->append(id_product);
166 return true;
167}
168
169bool GetUsbVersion(const Device& device, std::string* usb_version) {
170 return GetUsbProperty(device, "version", usb_version);
171}
172
173} // namespace cricket