summaryrefslogtreecommitdiff
path: root/utils/hwstub/lib
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2023-10-04 10:51:54 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2023-11-09 02:06:18 -0500
commit7f455af9053894241291f094865aee8808a1d3df (patch)
tree6ad266f617473f01e3de2f6e36cb47da10212166 /utils/hwstub/lib
parent154f10c2d2f32b24e51c1b3a232e2886cc834ff4 (diff)
downloadrockbox-7f455af9053894241291f094865aee8808a1d3df.tar.gz
rockbox-7f455af9053894241291f094865aee8808a1d3df.zip
hwstub lib: Introduce framework for device filtering
The rationale behind this was ability to filter usb device by bus numer and device address. This allows to connect with selected device in case there is more then one connected device implementing hwstub interface. For now only USB backend makes use of this but the foundation is generic and can be easily extended to other backends. Change-Id: I618cfdeeb09162d5fa1002db00e40ea17c43e727
Diffstat (limited to 'utils/hwstub/lib')
-rw-r--r--utils/hwstub/lib/hwstub_uri.cpp60
-rw-r--r--utils/hwstub/lib/hwstub_usb.cpp26
2 files changed, 73 insertions, 13 deletions
diff --git a/utils/hwstub/lib/hwstub_uri.cpp b/utils/hwstub/lib/hwstub_uri.cpp
index e2f252f3dc..e940fe69e2 100644
--- a/utils/hwstub/lib/hwstub_uri.cpp
+++ b/utils/hwstub/lib/hwstub_uri.cpp
@@ -48,8 +48,12 @@ void print_usage(FILE *f, bool client, bool server)
48 fprintf(f, " default Default choice made by the library\n"); 48 fprintf(f, " default Default choice made by the library\n");
49 if(client) 49 if(client)
50 { 50 {
51 fprintf(f, "When creating a USB context, the domain and port must be empty:\n"); 51 fprintf(f, "When creating a USB context, the domain and port represent usb_port and device_address\n");
52 fprintf(f, " usb:\n"); 52 fprintf(f, "as reported by lsusb. You can leave empty usb_port:device_address to match any usb device\n");
53 fprintf(f, "which provide hwstub interface\n");
54 fprintf(f, " usb://\n");
55 fprintf(f, "or\n");
56 fprintf(f, " usb://usb_port:device_address\n");
53 } 57 }
54 fprintf(f, "When creating a TCP context, the domain and port are the usual TCP parameters:\n"); 58 fprintf(f, "When creating a TCP context, the domain and port are the usual TCP parameters:\n");
55 fprintf(f, " tcp://localhost\n"); 59 fprintf(f, " tcp://localhost\n");
@@ -220,17 +224,55 @@ std::shared_ptr<context> create_context(const uri& uri, std::string *error)
220 /* handle different types of contexts */ 224 /* handle different types of contexts */
221 if(uri.scheme() == "usb") 225 if(uri.scheme() == "usb")
222 { 226 {
223 /* domain and port must be empty */ 227 if(!uri.domain().empty() && !uri.port().empty())
224 if(!uri.domain().empty() || !uri.port().empty()) 228 {
229 /** URI usb://usb_port:device_address
230 * for example usb://6:31
231 * usb_port and device_address match numbers
232 * reported by lsusb
233 *
234 * This filtering is additional to filtering
235 * by hwstub interface so final outcome will be device
236 * with usb_port:device_address which IS hwstub device
237 */
238 try
239 {
240 int bus = std::stoi(uri.domain());
241 int addr = std::stoi(uri.port());
242 libusb_context *ctx;
243 libusb_init(&ctx);
244
245 /** Build closure used to filter valid devices */
246 std::function<bool(void *)> f = [bus, addr](void *d){
247 libusb_device *dev = (libusb_device *)d;
248 return hwstub::usb::device::is_bus_addr_device(dev, bus, addr);
249 };
250
251 return hwstub::usb::context::create(ctx, true, nullptr, f);
252 }
253 catch(...)
254 {
255 if(error)
256 *error = "USB URI bus_port:device_address format error";
257 return std::shared_ptr<context>();
258 }
259 }
260 else if(uri.domain().empty() && uri.port().empty())
261 {
262 /** URI usb://
263 * No filtering, any usb device with hwstub
264 * interface will match
265 */
266 libusb_context *ctx;
267 libusb_init(&ctx);
268 return hwstub::usb::context::create(ctx, true);
269 }
270 else
225 { 271 {
226 if(error) 272 if(error)
227 *error = "USB URI cannot contain a domain or a port"; 273 *error = "USB URI format error";
228 return std::shared_ptr<context>(); 274 return std::shared_ptr<context>();
229 } 275 }
230 /* in doubt, create a new libusb context and let the context destroy it */
231 libusb_context *ctx;
232 libusb_init(&ctx);
233 return hwstub::usb::context::create(ctx, true);
234 } 276 }
235 else if(uri.scheme() == "virt") 277 else if(uri.scheme() == "virt")
236 { 278 {
diff --git a/utils/hwstub/lib/hwstub_usb.cpp b/utils/hwstub/lib/hwstub_usb.cpp
index e8b8e7bc3d..e6679ff780 100644
--- a/utils/hwstub/lib/hwstub_usb.cpp
+++ b/utils/hwstub/lib/hwstub_usb.cpp
@@ -41,20 +41,28 @@ context::context(libusb_context *ctx, bool cleanup_ctx)
41{ 41{
42} 42}
43 43
44context::context(libusb_context *ctx, bool cleanup_ctx, std::string *error, device_filter_t f)
45 :m_usb_ctx(ctx), m_cleanup_ctx(cleanup_ctx)
46{
47 (void)error;
48 // NOTE: can't use initializer list since this member is from parent class
49 // and parent's class constructor is NOT called when initializer list is built
50 device_filter = f;
51}
52
44context::~context() 53context::~context()
45{ 54{
46 if(m_cleanup_ctx) 55 if(m_cleanup_ctx)
47 libusb_exit(m_usb_ctx); 56 libusb_exit(m_usb_ctx);
48} 57}
49 58
50std::shared_ptr<context> context::create(libusb_context *ctx, bool cleanup_ctx, 59std::shared_ptr<context> context::create(libusb_context *ctx, bool cleanup_ctx, std::string *error, device_filter_t f)
51 std::string *error)
52{ 60{
53 (void) error; 61 (void) error;
54 if(ctx == nullptr) 62 if(ctx == nullptr)
55 libusb_init(nullptr); 63 libusb_init(nullptr);
56 // NOTE: can't use make_shared() because of the protected ctor */ 64 // NOTE: can't use make_shared() because of the protected ctor */
57 return std::shared_ptr<context>(new context(ctx, cleanup_ctx)); 65 return std::shared_ptr<context>(new context(ctx, cleanup_ctx, nullptr, f));
58} 66}
59 67
60libusb_context *context::native_context() 68libusb_context *context::native_context()
@@ -81,7 +89,11 @@ error context::fetch_device_list(std::vector<ctx_dev_t>& list, void*& ptr)
81 ptr = (void *)usb_list; 89 ptr = (void *)usb_list;
82 list.clear(); 90 list.clear();
83 for(int i = 0; i < ret; i++) 91 for(int i = 0; i < ret; i++)
84 if(device::is_hwstub_dev(usb_list[i])) 92 /* filter devices by hwstub interface and by other filtering criteria
93 * if provided
94 */
95 if(device::is_hwstub_dev(usb_list[i]) &&
96 context::device_filter(usb_list[i]))
85 list.push_back(to_ctx_dev(usb_list[i])); 97 list.push_back(to_ctx_dev(usb_list[i]));
86 return error::SUCCESS; 98 return error::SUCCESS;
87} 99}
@@ -231,6 +243,12 @@ uint16_t device::get_pid()
231 return dev_desc.idProduct; 243 return dev_desc.idProduct;
232} 244}
233 245
246bool device::is_bus_addr_device(libusb_device *dev, uint8_t bus, uint8_t addr)
247{
248 return ((libusb_get_bus_number(dev) == bus) &&
249 (libusb_get_device_address(dev) == addr));
250}
251
234/** 252/**
235 * USB handle 253 * USB handle
236 */ 254 */