1 /**
2  * Hotplug example using D-Language bindings to LibUSB-1.0
3  *
4  * Authors: Ross Lonstein <lonstein@brightboxcharge.com>
5  * License: LGPL
6  * Copyright: 2015, Brightbox, Inc.
7  * See_Also: http://libusbx.org
8  */
9 module hotplug;
10 
11 import core.thread;
12 import std.experimental.logger;
13 import libusb;
14 
15 int main(string[] args) {
16   int vendor_id  = 0xAFEF; // Change these to match a hotpluggable device on your system
17   int product_id = 0x0F01; //
18 
19   libusb_context *usbctx;
20 
21   log("Initializing USB library and context");
22   scope(exit) {
23     log("Releasing usb context");
24     libusb_exit(usbctx);
25   }
26   int rc = libusb_init(&usbctx);
27 
28   if (libusb_error.LIBUSB_SUCCESS == rc) {
29     log("Done.");
30   }
31   else {
32     warningf("Failed to init context: [%d] (%s), exiting...", rc, libusb_error_name(rc));
33     return -1;
34   }
35 
36   log("Setting debug on usb context...");
37   // change to "libusb_log_level.LIBUSB_LOG_LEVEL_DEBUG" for copious output
38   libusb_set_debug(usbctx, libusb_log_level.LIBUSB_LOG_LEVEL_INFO);
39 
40   log("Checking for hotplug capability...");
41   rc = libusb_has_capability(libusb_capability.LIBUSB_CAP_HAS_HOTPLUG);
42   if (rc != 0) {
43     log("API has hotplug capability");
44   }
45   else {
46     warningf("No hotplug support: [%d], aborting...", rc);
47     return -1;
48   }
49 
50   log("Registering hotplug callback...");
51   libusb_hotplug_callback_handle handle;
52   scope(exit) {
53     log("Releasing callback handle");
54     libusb_hotplug_deregister_callback(usbctx, handle);
55   }
56 
57   auto event_types = (LIBUSB_HOTPLUG_EVENTS.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
58                        LIBUSB_HOTPLUG_EVENTS.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
59 
60   auto flags = LIBUSB_HOTPLUG_ENUM.LIBUSB_HOTPLUG_ENUMERATE;
61   void  *user_data = null;
62 
63   rc = libusb_hotplug_register_callback(usbctx, event_types, flags,
64                                         vendor_id, product_id, LIBUSB_HOTPLUG_MATCH_ANY,
65                                         &hotplug_callback, user_data, &handle);
66 
67   if (libusb_error.LIBUSB_SUCCESS != rc) {
68     log("Failed to register callback");
69     return -1;
70   }
71 
72   while (true) {
73     rc = libusb_handle_events_completed(usbctx, null);
74     if (rc != 0) {
75       logf("Error %d ", rc);
76       break;
77     }
78     Thread.sleep(dur!("seconds")(5));
79   }
80   
81   return 0;
82 }
83 
84 
85 extern(C) int hotplug_callback(libusb_context *ctx, libusb_device *dev,
86                                libusb_hotplug_event event, void *user_data) {
87   libusb_device_handle *handle;
88   libusb_device_descriptor desc;
89   int rc;
90   
91   libusb_get_device_descriptor(dev, &desc);
92   if (LIBUSB_HOTPLUG_EVENTS.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
93     log("Hotplug connect event fired!");
94     rc = libusb_open(dev, &handle);
95     if (libusb_error.LIBUSB_SUCCESS != rc) {
96       log("Could not open USB device\n");
97     }
98     else {
99       log("Opened USB device");
100     }
101   }
102   else if (LIBUSB_HOTPLUG_EVENTS.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
103     log("Hotplug disconnect event fired!");
104     if (handle) {
105       log("Closing USB device");
106       libusb_close(handle);
107       handle = null;
108     }
109   }
110   else {
111     logf("Unhandled event %d\n", event);
112   }
113   return 0;
114 }