New upstream version 0.3.8
Mario Limonciello
2 years ago
0 | name: Build and Test | |
1 | ||
2 | on: | |
3 | push: | |
4 | branches: [ main ] | |
5 | pull_request: | |
6 | branches: [ main ] | |
7 | ||
8 | jobs: | |
9 | build-linux: | |
10 | runs-on: ubuntu-latest | |
11 | ||
12 | strategy: | |
13 | matrix: | |
14 | distro: | |
15 | - fedora | |
16 | - debian | |
17 | fail-fast: false | |
18 | ||
19 | steps: | |
20 | - uses: actions/checkout@v2 | |
21 | - run: docker build -t libgusb-${{ matrix.distro }} -f contrib/ci/Dockerfile-${{ matrix.distro }} . | |
22 | - run: docker run -t -v `pwd`:/build libgusb-${{ matrix.distro }} ./contrib/ci/build_and_test.sh -Dtests=false | |
23 | ||
24 | build-freebsd: | |
25 | runs-on: macos-latest | |
26 | ||
27 | steps: | |
28 | - name: Checkout | |
29 | uses: actions/checkout@v2 | |
30 | - name: Build | |
31 | id: test | |
32 | uses: vmactions/freebsd-vm@v0.1.4 | |
33 | with: | |
34 | usesh: true | |
35 | mem: 8192 | |
36 | prepare: | | |
37 | pkg install -y git python3 glib meson pkgconf gobject-introspection usbids | |
38 | sync: rsync | |
39 | run: ./contrib/ci/build_and_test.sh -Dvapi=false -Ddocs=false -Dusb_ids=/usr/local/share/usbids/usb.ids |
0 | language: c | |
1 | sudo: required | |
2 | dist: trusty | |
3 | ||
4 | services: | |
5 | - docker | |
6 | ||
7 | before_script: | |
8 | - docker build -t gusb-fedora -f contrib/ci/Dockerfile-fedora . | |
9 | # - docker build -t gusb-debian-stretch -f contrib/ci/Dockerfile-debian-stretch . | |
10 | ||
11 | script: | |
12 | - docker run -t -v `pwd`:/build gusb-fedora ./contrib/ci/build_and_test.sh -Dtests=false | |
13 | # - docker run -t -v `pwd`:/build gusb-debian-stretch ./contrib/ci/build_and_test.sh -Dtests=false |
0 | Version 0.3.8 | |
1 | ~~~~~~~~~~~~~ | |
2 | Released: 2021-10-06 | |
3 | ||
4 | New Features: | |
5 | - Add g_usb_device_get_string_descriptor_bytes_full (Ricardo CaƱuelo) | |
6 | ||
7 | Bugfixes: | |
8 | - Add the GUsbEndpoint methods to the docs (Richard Hughes) | |
9 | - Fix hotplug handling and signal emission during enumerate (Benjamin Berg) | |
10 | ||
11 | Version 0.3.7 | |
12 | ~~~~~~~~~~~~~ | |
13 | Released: 2021-05-24 | |
14 | ||
15 | New Features: | |
16 | - Add a FreeBSD CI target (Richard Hughes) | |
17 | ||
18 | Bugfixes: | |
19 | - Do not depend on libusb_get_parent() to fix FreeBSD compile (Richard Hughes) | |
20 | - Do not depend on libusb_get_port_number() to fix DragonFlyBSD compile (Richard Hughes) | |
21 | - Do not double-reference USB devices (Marco Trevisan) | |
22 | - Do not run the tests on FreeBSD (Richard Hughes) | |
23 | - Require *any* python3 to fix FreeBSD build (Richard Hughes) | |
24 | ||
25 | Version 0.3.6 | |
26 | ~~~~~~~~~~~~~ | |
27 | Released: 2021-03-12 | |
28 | ||
29 | New Features: | |
30 | - Add g_usb_device_get_string_descriptor_bytes() (Richard Hughes) | |
31 | ||
32 | Bugfixes: | |
33 | - Properly set dylib versions on darwin (Caleb Xu) | |
34 | - Fix cancellation if cancellable is already cancelled (Benjamin Berg) | |
35 | ||
0 | 36 | Version 0.3.5 |
1 | 37 | ~~~~~~~~~~~~~ |
2 | 38 | Released: 2020-07-30 |
2 | 2 | |
3 | 3 | Write `NEWS` entries for GUsb in the same format as usual. |
4 | 4 | |
5 | git shortlog 0.3.4.. | grep -i -v trivial | grep -v Merge > NEWS.new | |
5 | git shortlog 0.3.7.. | grep -i -v trivial | grep -v Merge > NEWS.new | |
6 | 6 | ================================================= |
7 | Version 0.3.5 | |
7 | Version 0.3.8 | |
8 | 8 | ~~~~~~~~~~~~~ |
9 | Released: 2020-xx-xx | |
9 | Released: 2021-xx-xx | |
10 | 10 | |
11 | 11 | Notes: |
12 | 12 | |
18 | 18 | Update library version if new ABI or API in `meson.build`, commit, and build tarball: |
19 | 19 | |
20 | 20 | # MAKE SURE THIS IS CORRECT |
21 | export release_ver="0.3.5" | |
21 | export release_ver="0.3.8" | |
22 | 22 | |
23 | 23 | git commit -a -m "Release version ${release_ver}" |
24 | 24 | git tag -s -f -m "Release ${release_ver}" "${release_ver}" |
40 | 40 | Send an email to devkit-devel@lists.freedesktop.org |
41 | 41 | |
42 | 42 | ================================================= |
43 | GUsb 0.3.5 released! | |
43 | GUsb 0.3.8 released! | |
44 | 44 | |
45 | 45 | GUsb is a GObject wrapper for libusb1 that makes it easy to do |
46 | 46 | asynchronous control, bulk and interrupt transfers with proper |
0 | FROM debian:buster | |
1 | ||
2 | RUN echo "deb-src http://deb.debian.org/debian/ buster main" >> /etc/apt/sources.list | |
3 | RUN apt-get update -qq | |
4 | RUN apt-get install -yq --no-install-recommends meson | |
5 | RUN apt-get build-dep --allow-unauthenticated -yq libgusb | |
6 | ||
7 | RUN mkdir /build | |
8 | WORKDIR /build |
0 | FROM debian:stretch | |
1 | ||
2 | RUN echo "deb-src http://deb.debian.org/debian/ stretch main" >> /etc/apt/sources.list | |
3 | RUN apt-get update -qq | |
4 | RUN apt-get install -yq --no-install-recommends meson | |
5 | RUN apt-get build-dep --allow-unauthenticated -yq libgusb | |
6 | ||
7 | RUN mkdir /build | |
8 | WORKDIR /build |
13 | 13 | BuildRequires: libusb1-devel >= 1.0.19 |
14 | 14 | BuildRequires: meson |
15 | 15 | BuildRequires: vala-devel |
16 | BuildRequires: vala-tools | |
17 | 16 | |
18 | 17 | %description |
19 | 18 | GUsb is a GObject wrapper for libusb1 that makes it easy to do |
50 | 50 | <xi:include href="xml/gusb-device.xml"/> |
51 | 51 | <xi:include href="xml/gusb-device-list.xml"/> |
52 | 52 | <xi:include href="xml/gusb-interface.xml"/> |
53 | <xi:include href="xml/gusb-endpoint.xml"/> | |
53 | 54 | </reference> |
54 | 55 | |
55 | 56 | <reference id="libgusb-helpers"> |
55 | 55 | libusb_hotplug_callback_handle hotplug_id; |
56 | 56 | }; |
57 | 57 | |
58 | /* not defined in FreeBSD */ | |
59 | #ifndef HAVE_LIBUSB_CAP_HAS_HOTPLUG | |
60 | #define LIBUSB_CAP_HAS_HOTPLUG 0x0001 | |
61 | #endif | |
62 | ||
58 | 63 | typedef struct { |
59 | 64 | GMainLoop *loop; |
60 | 65 | GUsbDevice *device; |
70 | 75 | G_ADD_PRIVATE (GUsbContext) |
71 | 76 | G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, |
72 | 77 | g_usb_context_initable_iface_init)) |
78 | ||
79 | /* not defined in FreeBSD */ | |
80 | #ifndef HAVE_LIBUSB_HAS_CAPABILITY | |
81 | static gboolean | |
82 | libusb_has_capability (int cap) | |
83 | { | |
84 | if (cap == LIBUSB_CAP_HAS_HOTPLUG) | |
85 | return TRUE; | |
86 | return FALSE; | |
87 | } | |
88 | #endif | |
73 | 89 | |
74 | 90 | static void |
75 | 91 | g_usb_context_replug_helper_free (GUsbContextReplugHelper *replug_helper) |
150 | 166 | switch (prop_id) { |
151 | 167 | case PROP_DEBUG_LEVEL: |
152 | 168 | priv->debug_level = g_value_get_int (value); |
153 | #ifdef HAVE_LIBUSB_1_0_22 | |
169 | #ifdef HAVE_LIBUSB_SET_OPTION | |
154 | 170 | libusb_set_option (priv->ctx, LIBUSB_OPTION_LOG_LEVEL, priv->debug_level); |
155 | 171 | #else |
156 | 172 | libusb_set_debug (priv->ctx, priv->debug_level); |
225 | 241 | G_USB_TYPE_DEVICE); |
226 | 242 | } |
227 | 243 | |
228 | typedef struct { | |
229 | GUsbContext *context; | |
230 | GUsbDevice *device; | |
231 | guint signal_id; | |
232 | } GUsbContextIdleHelper; | |
233 | ||
234 | static void | |
235 | g_usb_context_idle_helper_free (GUsbContextIdleHelper *helper) | |
236 | { | |
237 | g_object_unref (helper->context); | |
238 | g_object_unref (helper->device); | |
239 | g_free (helper); | |
240 | } | |
241 | ||
242 | static gboolean | |
243 | g_usb_context_idle_signal_cb (gpointer user_data) | |
244 | { | |
245 | GUsbContextIdleHelper *helper = (GUsbContextIdleHelper *) user_data; | |
246 | g_signal_emit (helper->context, signals[helper->signal_id], 0, helper->device); | |
247 | g_usb_context_idle_helper_free (helper); | |
248 | return FALSE; | |
249 | } | |
250 | ||
251 | 244 | static void |
252 | 245 | g_usb_context_emit_device_add (GUsbContext *context, |
253 | 246 | GUsbDevice *device) |
254 | 247 | { |
255 | GUsbContextIdleHelper *helper; | |
256 | helper = g_new0 (GUsbContextIdleHelper, 1); | |
257 | helper->context = g_object_ref (context); | |
258 | helper->device = g_object_ref (device); | |
259 | helper->signal_id = DEVICE_ADDED_SIGNAL; | |
260 | if (!context->priv->done_enumerate) { | |
261 | g_usb_context_idle_signal_cb (helper); | |
248 | /* emitted directly by g_usb_context_enumerate */ | |
249 | if (!context->priv->done_enumerate) | |
262 | 250 | return; |
263 | } | |
264 | g_idle_add (g_usb_context_idle_signal_cb, helper); | |
251 | ||
252 | g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device); | |
265 | 253 | } |
266 | 254 | |
267 | 255 | static void |
268 | 256 | g_usb_context_emit_device_remove (GUsbContext *context, |
269 | 257 | GUsbDevice *device) |
270 | 258 | { |
271 | GUsbContextIdleHelper *helper; | |
272 | helper = g_new0 (GUsbContextIdleHelper, 1); | |
273 | helper->context = g_object_ref (context); | |
274 | helper->device = g_object_ref (device); | |
275 | helper->signal_id = DEVICE_REMOVED_SIGNAL; | |
276 | if (!context->priv->done_enumerate) { | |
277 | g_usb_context_idle_signal_cb (helper); | |
259 | /* should not happen, if it does we would not fire any signal */ | |
260 | if (!context->priv->done_enumerate) | |
278 | 261 | return; |
279 | } | |
280 | g_idle_add (g_usb_context_idle_signal_cb, helper); | |
262 | ||
263 | g_signal_emit (context, signals[DEVICE_REMOVED_SIGNAL], 0, device); | |
281 | 264 | } |
282 | 265 | |
283 | 266 | static void |
379 | 362 | g_object_unref (device); |
380 | 363 | } |
381 | 364 | |
365 | typedef struct { | |
366 | GUsbContext *context; | |
367 | libusb_device *dev; | |
368 | libusb_hotplug_event event; | |
369 | } GUsbContextIdleHelper; | |
370 | ||
371 | static void | |
372 | g_usb_context_idle_helper_free (GUsbContextIdleHelper *helper) | |
373 | { | |
374 | g_object_unref (helper->context); | |
375 | libusb_unref_device (helper->dev); | |
376 | g_free (helper); | |
377 | } | |
378 | ||
379 | static gboolean | |
380 | g_usb_context_idle_hotplug_cb (gpointer user_data) | |
381 | { | |
382 | GUsbContextIdleHelper *helper = (GUsbContextIdleHelper *) user_data; | |
383 | ||
384 | switch (helper->event) { | |
385 | case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: | |
386 | g_usb_context_add_device (helper->context, helper->dev); | |
387 | break; | |
388 | case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: | |
389 | g_usb_context_remove_device (helper->context, helper->dev); | |
390 | break; | |
391 | default: | |
392 | break; | |
393 | } | |
394 | ||
395 | g_usb_context_idle_helper_free (helper); | |
396 | return FALSE; | |
397 | } | |
398 | ||
382 | 399 | static int |
383 | 400 | g_usb_context_hotplug_cb (struct libusb_context *ctx, |
384 | 401 | struct libusb_device *dev, |
386 | 403 | void *user_data) |
387 | 404 | { |
388 | 405 | GUsbContext *context = G_USB_CONTEXT (user_data); |
389 | ||
390 | switch (event) { | |
391 | case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: | |
392 | g_usb_context_add_device (context, dev); | |
393 | break; | |
394 | case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: | |
395 | g_usb_context_remove_device (context, dev); | |
396 | break; | |
397 | default: | |
398 | break; | |
399 | } | |
406 | GUsbContextIdleHelper *helper; | |
407 | ||
408 | helper = g_new0 (GUsbContextIdleHelper, 1); | |
409 | helper->context = context; | |
410 | helper->dev = libusb_ref_device (dev); | |
411 | helper->event = event; | |
412 | ||
413 | g_idle_add (g_usb_context_idle_hotplug_cb, helper); | |
414 | ||
400 | 415 | return 0; |
401 | 416 | } |
402 | 417 | |
451 | 466 | return TRUE; |
452 | 467 | } |
453 | 468 | |
454 | ||
455 | 469 | /** |
456 | 470 | * g_usb_context_get_main_context: |
457 | 471 | * @context: a #GUsbContext |
522 | 536 | context); |
523 | 537 | } |
524 | 538 | priv->done_enumerate = TRUE; |
539 | ||
540 | /* emit device-added signals before returning */ | |
541 | for (guint i = 0; i < priv->devices->len; i++) | |
542 | g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, | |
543 | g_ptr_array_index (priv->devices, i)); | |
544 | ||
545 | /* any queued up hotplug events are queued as idle handlers */ | |
525 | 546 | } |
526 | 547 | |
527 | 548 | /** |
709 | 730 | |
710 | 731 | if (debug_level != priv->debug_level) { |
711 | 732 | priv->debug_level = debug_level; |
712 | #ifdef HAVE_LIBUSB_1_0_22 | |
733 | #ifdef HAVE_LIBUSB_SET_OPTION | |
713 | 734 | libusb_set_option (priv->ctx, LIBUSB_OPTION_LOG_LEVEL, debug_level); |
714 | 735 | #else |
715 | 736 | libusb_set_debug (priv->ctx, debug_level); |
109 | 109 | } |
110 | 110 | |
111 | 111 | static void |
112 | set_libusb_device (GUsbDevice *device, | |
113 | struct libusb_device *dev) | |
114 | { | |
115 | GUsbDevicePrivate *priv = device->priv; | |
116 | ||
117 | g_clear_pointer (&priv->device, libusb_unref_device); | |
118 | ||
119 | if (dev != NULL) | |
120 | priv->device = libusb_ref_device (dev); | |
121 | } | |
122 | ||
123 | static void | |
112 | 124 | g_usb_device_set_property (GObject *object, |
113 | 125 | guint prop_id, |
114 | 126 | const GValue *value, |
119 | 131 | |
120 | 132 | switch (prop_id) { |
121 | 133 | case PROP_LIBUSB_DEVICE: |
122 | priv->device = g_value_get_pointer (value); | |
134 | set_libusb_device (device, g_value_get_pointer (value)); | |
123 | 135 | break; |
124 | 136 | case PROP_CONTEXT: |
125 | 137 | priv->context = g_value_dup_object (value); |
144 | 156 | |
145 | 157 | if (!priv->device) |
146 | 158 | g_error("constructed without a libusb_device"); |
147 | ||
148 | libusb_ref_device(priv->device); | |
149 | 159 | |
150 | 160 | rc = libusb_get_device_descriptor (priv->device, &priv->desc); |
151 | 161 | if (rc != LIBUSB_SUCCESS) |
201 | 211 | device->priv = g_usb_device_get_instance_private (device); |
202 | 212 | } |
203 | 213 | |
214 | /* not defined in FreeBSD */ | |
215 | #ifndef HAVE_LIBUSB_GET_PARENT | |
216 | static libusb_device * | |
217 | libusb_get_parent (libusb_device *dev) | |
218 | { | |
219 | return NULL; | |
220 | } | |
221 | #endif | |
222 | ||
223 | /* not defined in DragonFlyBSD */ | |
224 | #ifndef HAVE_LIBUSB_GET_PORT_NUMBER | |
225 | static guint8 | |
226 | libusb_get_port_number (libusb_device *dev) | |
227 | { | |
228 | return 0xff; | |
229 | } | |
230 | #endif | |
231 | ||
204 | 232 | static void |
205 | 233 | g_usb_device_build_parent_port_number (GString *str, libusb_device *dev) |
206 | 234 | { |
239 | 267 | "Constructed without a libusb_device"); |
240 | 268 | return FALSE; |
241 | 269 | } |
242 | ||
243 | libusb_ref_device (priv->device); | |
244 | 270 | |
245 | 271 | rc = libusb_get_device_descriptor (priv->device, &priv->desc); |
246 | 272 | if (rc != LIBUSB_SUCCESS) { |
888 | 914 | return g_strdup ((const gchar *)buf); |
889 | 915 | } |
890 | 916 | |
917 | /** | |
918 | * g_usb_device_get_string_descriptor_bytes_full: | |
919 | * @desc_index: the index for the string descriptor to retrieve | |
920 | * @langid: the language ID | |
921 | * @length: size of the request data buffer | |
922 | * @error: a #GError, or %NULL | |
923 | * | |
924 | * Get a raw string descriptor from the device. The returned string should be freed | |
925 | * with g_bytes_unref() when no longer needed. | |
926 | * | |
927 | * Return value: (transfer full): a possibly UTF-16 string, or NULL on error. | |
928 | * | |
929 | * Since: 0.3.8 | |
930 | **/ | |
931 | GBytes * | |
932 | g_usb_device_get_string_descriptor_bytes_full (GUsbDevice *device, | |
933 | guint8 desc_index, | |
934 | guint16 langid, | |
935 | gsize length, | |
936 | GError **error) | |
937 | { | |
938 | gint rc; | |
939 | g_autofree guint8 *buf = g_malloc0(length); | |
940 | ||
941 | g_return_val_if_fail (G_USB_IS_DEVICE (device), NULL); | |
942 | g_return_val_if_fail (error == NULL || *error == NULL, NULL); | |
943 | ||
944 | if (device->priv->handle == NULL) { | |
945 | g_usb_device_not_open_error (device, error); | |
946 | return NULL; | |
947 | } | |
948 | ||
949 | rc = libusb_get_string_descriptor (device->priv->handle, | |
950 | desc_index, langid, | |
951 | buf, length); | |
952 | if (rc < 0) { | |
953 | g_usb_device_libusb_error_to_gerror (device, rc, error); | |
954 | return NULL; | |
955 | } | |
956 | ||
957 | return g_bytes_new (buf, rc); | |
958 | } | |
959 | ||
960 | /** | |
961 | * g_usb_device_get_string_descriptor_bytes: | |
962 | * @desc_index: the index for the string descriptor to retrieve | |
963 | * @langid: the language ID | |
964 | * @error: a #GError, or %NULL | |
965 | * | |
966 | * Get a raw string descriptor from the device. The returned string should be freed | |
967 | * with g_bytes_unref() when no longer needed. | |
968 | * The descriptor will be at most 128 btes in length, if you need to | |
969 | * issue a request with either a smaller or larger descriptor, you can | |
970 | * use g_usb_device_get_string_descriptor_bytes_full instead. | |
971 | * | |
972 | * Return value: (transfer full): a possibly UTF-16 string, or NULL on error. | |
973 | * | |
974 | * Since: 0.3.6 | |
975 | **/ | |
976 | GBytes * | |
977 | g_usb_device_get_string_descriptor_bytes (GUsbDevice *device, | |
978 | guint8 desc_index, | |
979 | guint16 langid, | |
980 | GError **error) | |
981 | { | |
982 | return g_usb_device_get_string_descriptor_bytes_full(device, | |
983 | desc_index, | |
984 | langid, | |
985 | 128, | |
986 | error); | |
987 | } | |
988 | ||
891 | 989 | typedef gssize (GUsbDeviceTransferFinishFunc) (GUsbDevice *device, GAsyncResult *res, GError **error); |
892 | 990 | |
893 | 991 | typedef struct { |
918 | 1016 | * either input or output |
919 | 1017 | * @length: the length field for the setup packet. |
920 | 1018 | * @actual_length: (out) (optional): the actual number of bytes sent, or %NULL |
921 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1019 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
922 | 1020 | * before giving up due to no response being received. For an unlimited |
923 | 1021 | * timeout, use 0. |
924 | 1022 | * @cancellable: a #GCancellable, or %NULL |
985 | 1083 | * either input or output |
986 | 1084 | * @length: the length field for the setup packet. |
987 | 1085 | * @actual_length: (out) (optional): the actual number of bytes sent, or %NULL |
988 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1086 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
989 | 1087 | * before giving up due to no response being received. For an unlimited |
990 | 1088 | * timeout, use 0. |
991 | 1089 | * @cancellable: a #GCancellable, or %NULL |
1042 | 1140 | * either input or output |
1043 | 1141 | * @length: the length field for the setup packet. |
1044 | 1142 | * @actual_length: (out) (optional): the actual number of bytes sent, or %NULL |
1045 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1143 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
1046 | 1144 | * before giving up due to no response being received. For an unlimited |
1047 | 1145 | * timeout, use 0. |
1048 | 1146 | * @cancellable: a #GCancellable, or %NULL |
1222 | 1320 | * @data: (array length=length): a suitably-sized data buffer for |
1223 | 1321 | * either input or output |
1224 | 1322 | * @length: the length field for the setup packet. |
1225 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1323 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
1226 | 1324 | * before giving up due to no response being received. For an unlimited |
1227 | 1325 | * timeout, use 0. |
1228 | 1326 | * @cancellable: a #GCancellable, or %NULL |
1266 | 1364 | req->transfer = libusb_alloc_transfer (0); |
1267 | 1365 | req->data = data; |
1268 | 1366 | |
1269 | /* setup cancellation */ | |
1270 | if (cancellable != NULL) { | |
1271 | req->cancellable = g_object_ref (cancellable); | |
1272 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1273 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1274 | req, | |
1275 | NULL); | |
1276 | } | |
1277 | ||
1278 | 1367 | task = g_task_new (device, cancellable, callback, user_data); |
1279 | 1368 | g_task_set_task_data (task, req, (GDestroyNotify)g_usb_device_req_free); |
1369 | ||
1370 | if (g_task_return_error_if_cancelled (task)) { | |
1371 | g_object_unref (task); | |
1372 | return; | |
1373 | } | |
1280 | 1374 | |
1281 | 1375 | /* munge back to flags */ |
1282 | 1376 | if (direction == G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST) |
1306 | 1400 | g_task_return_error (task, error); |
1307 | 1401 | g_object_unref (task); |
1308 | 1402 | } |
1403 | ||
1404 | /* setup cancellation after submission */ | |
1405 | if (cancellable != NULL) { | |
1406 | req->cancellable = g_object_ref (cancellable); | |
1407 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1408 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1409 | req, | |
1410 | NULL); | |
1411 | } | |
1309 | 1412 | } |
1310 | 1413 | |
1311 | 1414 | /** |
1339 | 1442 | * @data: (array length=length): a suitably-sized data buffer for |
1340 | 1443 | * either input or output |
1341 | 1444 | * @length: the length field for the setup packet. |
1342 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1445 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
1343 | 1446 | * before giving up due to no response being received. For an unlimited |
1344 | 1447 | * timeout, use 0. |
1345 | 1448 | * @cancellable: a #GCancellable, or %NULL |
1376 | 1479 | req = g_slice_new0 (GcmDeviceReq); |
1377 | 1480 | req->transfer = libusb_alloc_transfer (0); |
1378 | 1481 | |
1379 | /* setup cancellation */ | |
1380 | if (cancellable != NULL) { | |
1381 | req->cancellable = g_object_ref (cancellable); | |
1382 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1383 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1384 | req, | |
1385 | NULL); | |
1386 | } | |
1387 | ||
1388 | 1482 | task = g_task_new (device, cancellable, callback, user_data); |
1389 | 1483 | g_task_set_task_data (task, req, (GDestroyNotify)g_usb_device_req_free); |
1484 | ||
1485 | if (g_task_return_error_if_cancelled (task)) { | |
1486 | g_object_unref (task); | |
1487 | return; | |
1488 | } | |
1390 | 1489 | |
1391 | 1490 | /* fill in transfer details */ |
1392 | 1491 | libusb_fill_bulk_transfer (req->transfer, |
1405 | 1504 | g_task_return_error (task, error); |
1406 | 1505 | g_object_unref (task); |
1407 | 1506 | } |
1507 | ||
1508 | /* setup cancellation after submission */ | |
1509 | if (cancellable != NULL) { | |
1510 | req->cancellable = g_object_ref (cancellable); | |
1511 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1512 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1513 | req, | |
1514 | NULL); | |
1515 | } | |
1408 | 1516 | } |
1409 | 1517 | |
1410 | 1518 | /** |
1438 | 1546 | * @data: (array length=length): a suitably-sized data buffer for |
1439 | 1547 | * either input or output |
1440 | 1548 | * @length: the length field for the setup packet. |
1441 | * @timeout: timeout timeout (in millseconds) that this function should wait | |
1549 | * @timeout: timeout timeout (in milliseconds) that this function should wait | |
1442 | 1550 | * before giving up due to no response being received. For an unlimited |
1443 | 1551 | * timeout, use 0. |
1444 | 1552 | * @cancellable: a #GCancellable, or %NULL |
1475 | 1583 | req = g_slice_new0 (GcmDeviceReq); |
1476 | 1584 | req->transfer = libusb_alloc_transfer (0); |
1477 | 1585 | |
1478 | /* setup cancellation */ | |
1479 | if (cancellable != NULL) { | |
1480 | req->cancellable = g_object_ref (cancellable); | |
1481 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1482 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1483 | req, | |
1484 | NULL); | |
1485 | } | |
1486 | ||
1487 | 1586 | task = g_task_new (device, cancellable, callback, user_data); |
1488 | 1587 | g_task_set_task_data (task, req, (GDestroyNotify)g_usb_device_req_free); |
1588 | ||
1589 | if (g_task_return_error_if_cancelled (task)) { | |
1590 | g_object_unref (task); | |
1591 | return; | |
1592 | } | |
1489 | 1593 | |
1490 | 1594 | /* fill in transfer details */ |
1491 | 1595 | libusb_fill_interrupt_transfer (req->transfer, |
1504 | 1608 | g_task_return_error (task, error); |
1505 | 1609 | g_object_unref (task); |
1506 | 1610 | } |
1611 | ||
1612 | /* setup cancellation after submission */ | |
1613 | if (cancellable != NULL) { | |
1614 | req->cancellable = g_object_ref (cancellable); | |
1615 | req->cancellable_id = g_cancellable_connect (req->cancellable, | |
1616 | G_CALLBACK (g_usb_device_cancelled_cb), | |
1617 | req, | |
1618 | NULL); | |
1619 | } | |
1507 | 1620 | } |
1508 | 1621 | |
1509 | 1622 | /** |
117 | 117 | G_USB_DEVICE_CLASS_VENDOR_SPECIFIC = 0xff |
118 | 118 | } GUsbDeviceClassCode; |
119 | 119 | |
120 | ||
121 | /** | |
122 | * GUsbDeviceLangid: | |
123 | * | |
124 | * The USB language ID. | |
125 | **/ | |
126 | typedef enum { | |
127 | G_USB_DEVICE_LANGID_INVALID = 0x0000, | |
128 | G_USB_DEVICE_LANGID_ENGLISH_UNITED_STATES = 0x0409, | |
129 | } GUsbDeviceLangid; | |
130 | ||
120 | 131 | struct _GUsbDevice |
121 | 132 | { |
122 | 133 | GObject parent; |
200 | 211 | guint8 alt, |
201 | 212 | GError **error); |
202 | 213 | |
203 | gchar *g_usb_device_get_string_descriptor (GUsbDevice *device, | |
204 | guint8 desc_index, | |
205 | GError **error); | |
214 | gchar *g_usb_device_get_string_descriptor (GUsbDevice *device, | |
215 | guint8 desc_index, | |
216 | GError **error); | |
217 | GBytes *g_usb_device_get_string_descriptor_bytes (GUsbDevice *device, | |
218 | guint8 desc_index, | |
219 | guint16 langid, | |
220 | GError **error); | |
221 | GBytes *g_usb_device_get_string_descriptor_bytes_full (GUsbDevice *device, | |
222 | guint8 desc_index, | |
223 | guint16 langid, | |
224 | gsize length, | |
225 | GError **error); | |
206 | 226 | |
207 | 227 | /* sync -- TODO: use GCancellable and GUsbSource */ |
208 | 228 | gboolean g_usb_device_control_transfer (GUsbDevice *device, |
11 | 11 | * This object is a thin glib wrapper around a libusb_endpoint_descriptor. |
12 | 12 | * |
13 | 13 | * All the data is copied when the object is created and the original |
14 | * descriptor can be destoyed any at point. | |
14 | * descriptor can be destroyed any at point. | |
15 | 15 | */ |
16 | 16 | |
17 | 17 | #include "config.h" |
18 | ||
19 | #include <string.h> | |
18 | 20 | |
19 | 21 | #include "gusb-endpoint.h" |
20 | 22 | #include "gusb-endpoint-private.h" |
12 | 12 | * This object is a thin glib wrapper around a libusb_interface_descriptor. |
13 | 13 | * |
14 | 14 | * All the data is copied when the object is created and the original |
15 | * descriptor can be destoyed any at point. | |
15 | * descriptor can be destroyed any at point. | |
16 | 16 | */ |
17 | 17 | |
18 | 18 | #include "config.h" |
19 | 19 | GPtrArray *array; |
20 | 20 | GUsbContext *ctx; |
21 | 21 | GUsbDevice *device; |
22 | ||
23 | #ifdef __FreeBSD__ | |
24 | g_test_skip ("Root hubs on FreeBSD have vid and pid set to zero"); | |
25 | return; | |
26 | #endif | |
22 | 27 | |
23 | 28 | ctx = g_usb_context_new (&error); |
24 | 29 | g_assert_no_error (error); |
69 | 74 | gchar *manufacturer; |
70 | 75 | gchar *product; |
71 | 76 | guint i; |
77 | ||
78 | #ifdef __FreeBSD__ | |
79 | g_test_skip ("Root hubs on FreeBSD have vid and pid set to zero"); | |
80 | return; | |
81 | #endif | |
72 | 82 | |
73 | 83 | ctx = g_usb_context_new (&error); |
74 | 84 | g_assert_no_error (error); |
146 | 146 | g_usb_device_get_configuration_index; |
147 | 147 | local: *; |
148 | 148 | } LIBGUSB_0.3.3; |
149 | ||
150 | LIBGUSB_0.3.6 { | |
151 | global: | |
152 | g_usb_device_get_string_descriptor_bytes; | |
153 | local: *; | |
154 | } LIBGUSB_0.3.5; | |
155 | ||
156 | LIBGUSB_0.3.8 { | |
157 | global: | |
158 | g_usb_device_get_string_descriptor_bytes_full; | |
159 | local: *; | |
160 | } LIBGUSB_0.3.6; |
60 | 60 | ], |
61 | 61 | soversion : lt_current, |
62 | 62 | version : lt_version, |
63 | darwin_versions: [lt_current + 1, '@0@.@1@.0'.format(lt_current + 1, lt_revision)], | |
63 | 64 | dependencies : [ |
64 | 65 | libgio, |
65 | 66 | libusb, |
86 | 87 | ) |
87 | 88 | |
88 | 89 | pkgg = import('pkgconfig') |
89 | pkgg.generate( | |
90 | libraries : gusb, | |
90 | pkgg.generate(gusb, | |
91 | 91 | requires : [ 'gio-2.0', 'gobject-2.0', 'libusb-1.0' ], |
92 | 92 | subdirs : 'gusb-1', |
93 | 93 | version : meson.project_version(), |
145 | 145 | libgusb_typelib = libgusb_girtarget[1] |
146 | 146 | |
147 | 147 | pymod = import('python') |
148 | py_installation = pymod.find_installation('python3') | |
148 | py_installation = pymod.find_installation() | |
149 | 149 | |
150 | 150 | # Verify the map file is correct -- note we can't actually use the generated |
151 | 151 | # file for two reasons: |
0 | 0 | project('libgusb', 'c', |
1 | version : '0.3.5', | |
1 | version : '0.3.8', | |
2 | 2 | license : 'LGPL-2.1+', |
3 | 3 | meson_version : '>=0.46.0', |
4 | 4 | default_options : ['c_std=c99'] |
14 | 14 | conf.set_quoted('VERSION', gusb_version) |
15 | 15 | |
16 | 16 | # libtool versioning - this applies to libgusb |
17 | lt_current = '2' | |
18 | lt_revision = '10' | |
19 | lt_age = '0' | |
17 | lt_current = 2 | |
18 | lt_revision = 10 | |
19 | lt_age = 0 | |
20 | 20 | lt_version = '@0@.@1@.@2@'.format(lt_current, lt_age, lt_revision) |
21 | 21 | |
22 | 22 | # get supported warning flags |
93 | 93 | ) |
94 | 94 | |
95 | 95 | libgio = dependency('gio-2.0', version : '>= 2.44.0') |
96 | libusb = dependency('libusb-1.0', version : '>= 1.0.19') | |
97 | if libusb.version().version_compare ('>= 1.0.22') | |
98 | conf.set('HAVE_LIBUSB_1_0_22', '1') | |
96 | libusb = dependency('libusb-1.0', version : '>= 1.0.9') | |
97 | if cc.has_header_symbol('libusb.h', 'LIBUSB_CAP_HAS_HOTPLUG', dependencies: libusb) | |
98 | conf.set('HAVE_LIBUSB_CAP_HAS_HOTPLUG', '1') | |
99 | endif | |
100 | if cc.has_header_symbol('libusb.h', 'libusb_has_capability', dependencies: libusb) | |
101 | conf.set('HAVE_LIBUSB_HAS_CAPABILITY', '1') | |
102 | endif | |
103 | if cc.has_header_symbol('libusb.h', 'libusb_set_option', dependencies: libusb) | |
104 | conf.set('HAVE_LIBUSB_SET_OPTION', '1') | |
105 | endif | |
106 | if cc.has_header_symbol('libusb.h', 'libusb_get_parent', dependencies: libusb) | |
107 | conf.set('HAVE_LIBUSB_GET_PARENT', '1') | |
108 | endif | |
109 | if cc.has_header_symbol('libusb.h', 'libusb_get_port_number', dependencies: libusb) | |
110 | conf.set('HAVE_LIBUSB_GET_PORT_NUMBER', '1') | |
99 | 111 | endif |
100 | 112 | |
101 | 113 | gusb_deps = [ |
152 | 152 | return; |
153 | 153 | } |
154 | 154 | g_print ("product: %s\n", product); |
155 | g_free (product); | |
155 | 156 | } |
156 | 157 | } |
157 | 158 | |
436 | 437 | |
437 | 438 | priv->context = g_option_context_new ("GUSB Console Program"); |
438 | 439 | g_option_context_add_main_entries (priv->context, options, NULL); |
439 | g_option_context_parse (priv->context, &argc, &argv, NULL); | |
440 | if (!g_option_context_parse (priv->context, &argc, &argv, &error)) { | |
441 | g_printerr ("Failed to parse arguments: %s\n", error->message); | |
442 | g_error_free (error); | |
443 | retval = 2; | |
444 | goto out; | |
445 | } | |
440 | 446 | |
441 | 447 | /* verbose? */ |
442 | 448 | if (verbose) { |