50
50
struct bluez_midi_app {
51
51
/* D-Bus object registration paths */
52
52
char path [64 ];
53
+ char path_adv [64 + 8 ];
53
54
char path_service [64 + 8 ];
54
55
char path_char [64 + 16 ];
55
56
/* associated adapter */
@@ -69,14 +70,6 @@ struct bluez_midi_app {
69
70
* D-Bus unique name of the BlueZ daemon. */
70
71
static char bluez_dbus_unique_name [64 ] = "" ;
71
72
72
- static GVariant * variant_new_midi_service_uuid (void ) {
73
- return g_variant_new_string (BT_UUID_MIDI );
74
- }
75
-
76
- static GVariant * variant_new_midi_characteristic_uuid (void ) {
77
- return g_variant_new_string (BT_UUID_MIDI_CHAR );
78
- }
79
-
80
73
static struct bluez_midi_app * bluez_midi_app_ref (struct bluez_midi_app * app ) {
81
74
atomic_fetch_add_explicit (& app -> ref_count , 1 , memory_order_relaxed );
82
75
return app ;
@@ -128,12 +121,70 @@ static struct ba_transport *bluez_midi_transport_new(
128
121
return t ;
129
122
}
130
123
124
+ static void bluez_midi_advertisement_release (
125
+ GDBusMethodInvocation * inv , void * userdata ) {
126
+ struct bluez_midi_app * app = userdata ;
127
+ debug ("Releasing MIDI LE advertisement: %s" , app -> path );
128
+ g_object_unref (inv );
129
+ }
130
+
131
+ static GVariant * bluez_midi_advertisement_iface_get_property (
132
+ const char * property , G_GNUC_UNUSED GError * * error , void * userdata ) {
133
+ (void )userdata ;
134
+
135
+ if (strcmp (property , "Type" ) == 0 )
136
+ return g_variant_new_string ("peripheral" );
137
+ if (strcmp (property , "ServiceUUIDs" ) == 0 ) {
138
+ static const char * uuids [] = { BT_UUID_MIDI };
139
+ return g_variant_new_strv (uuids , ARRAYSIZE (uuids ));
140
+ }
141
+ if (strcmp (property , "Discoverable" ) == 0 )
142
+ /* advertise as general discoverable LE-only device */
143
+ return g_variant_new_boolean (TRUE);
144
+ if (strcmp (property , "Includes" ) == 0 ) {
145
+ const char * values [] = { "local-name" };
146
+ return g_variant_new_strv (values , ARRAYSIZE (values ));
147
+ }
148
+
149
+ g_assert_not_reached ();
150
+ return NULL ;
151
+ }
152
+
153
+ static GDBusObjectSkeleton * bluez_midi_advertisement_skeleton_new (
154
+ struct bluez_midi_app * app ) {
155
+
156
+ static const GDBusMethodCallDispatcher dispatchers [] = {
157
+ { .method = "Release" ,
158
+ .sender = bluez_dbus_unique_name ,
159
+ .handler = bluez_midi_advertisement_release },
160
+ { 0 },
161
+ };
162
+
163
+ static const GDBusInterfaceSkeletonVTable vtable = {
164
+ .dispatchers = dispatchers ,
165
+ .get_property = bluez_midi_advertisement_iface_get_property ,
166
+ };
167
+
168
+ OrgBluezLeadvertisement1Skeleton * ifs_gatt_adv ;
169
+ if ((ifs_gatt_adv = org_bluez_leadvertisement1_skeleton_new (& vtable ,
170
+ app , (GDestroyNotify )bluez_midi_app_unref )) == NULL )
171
+ return NULL ;
172
+
173
+ GDBusInterfaceSkeleton * ifs = G_DBUS_INTERFACE_SKELETON (ifs_gatt_adv );
174
+ GDBusObjectSkeleton * skeleton = g_dbus_object_skeleton_new (app -> path_adv );
175
+ g_dbus_object_skeleton_add_interface (skeleton , ifs );
176
+ g_object_unref (ifs_gatt_adv );
177
+
178
+ bluez_midi_app_ref (app );
179
+ return skeleton ;
180
+ }
181
+
131
182
static GVariant * bluez_midi_service_iface_get_property (
132
183
const char * property , G_GNUC_UNUSED GError * * error ,
133
184
G_GNUC_UNUSED void * userdata ) {
134
185
135
186
if (strcmp (property , "UUID" ) == 0 )
136
- return variant_new_midi_service_uuid ( );
187
+ return g_variant_new_string ( BT_UUID_MIDI );
137
188
if (strcmp (property , "Primary" ) == 0 )
138
189
return g_variant_new_boolean (TRUE);
139
190
@@ -198,7 +249,7 @@ static void bluez_midi_characteristic_acquire_write(
198
249
}
199
250
200
251
int fds [2 ];
201
- if (socketpair (AF_LOCAL , SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 , fds ) == -1 ) {
252
+ if (socketpair (AF_UNIX , SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 , fds ) == -1 ) {
202
253
error ("Couldn't create BLE-MIDI char write socket pair: %s" , strerror (errno ));
203
254
goto fail ;
204
255
}
@@ -258,7 +309,7 @@ static void bluez_midi_characteristic_acquire_notify(
258
309
}
259
310
260
311
int fds [2 ];
261
- if (socketpair (AF_LOCAL , SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 , fds ) == -1 ) {
312
+ if (socketpair (AF_UNIX , SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 , fds ) == -1 ) {
262
313
error ("Couldn't create BLE-MIDI char notify socket pair: %s" , strerror (errno ));
263
314
goto fail ;
264
315
}
@@ -294,7 +345,7 @@ static GVariant *bluez_midi_characteristic_iface_get_property(
294
345
struct bluez_midi_app * app = userdata ;
295
346
296
347
if (strcmp (property , "UUID" ) == 0 )
297
- return variant_new_midi_characteristic_uuid ( );
348
+ return g_variant_new_string ( BT_UUID_MIDI_CHAR );
298
349
if (strcmp (property , "Service" ) == 0 )
299
350
return g_variant_new_object_path (app -> path_service );
300
351
if (strcmp (property , "WriteAcquired" ) == 0 )
@@ -371,6 +422,59 @@ static void bluez_midi_app_register_finish(
371
422
372
423
}
373
424
425
+ static void bluez_midi_app_register (
426
+ struct ba_adapter * adapter , struct bluez_midi_app * app ) {
427
+
428
+ GDBusMessage * msg ;
429
+ msg = g_dbus_message_new_method_call (BLUEZ_SERVICE , adapter -> bluez_dbus_path ,
430
+ BLUEZ_IFACE_GATT_MANAGER , "RegisterApplication" );
431
+
432
+ g_dbus_message_set_body (msg , g_variant_new ("(oa{sv})" , app -> path , NULL ));
433
+
434
+ debug ("Registering MIDI GATT application: %s" , app -> path );
435
+ g_dbus_connection_send_message_with_reply (config .dbus , msg ,
436
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE , -1 , NULL , NULL ,
437
+ bluez_midi_app_register_finish , NULL );
438
+
439
+ g_object_unref (msg );
440
+ }
441
+
442
+ static void bluez_midi_app_advertise_finish (
443
+ GObject * source , GAsyncResult * result , G_GNUC_UNUSED void * userdata ) {
444
+
445
+ GError * err = NULL ;
446
+ GDBusMessage * rep ;
447
+
448
+ if ((rep = g_dbus_connection_send_message_with_reply_finish (
449
+ G_DBUS_CONNECTION (source ), result , & err )) != NULL )
450
+ g_dbus_message_to_gerror (rep , & err );
451
+
452
+ if (rep != NULL )
453
+ g_object_unref (rep );
454
+ if (err != NULL ) {
455
+ error ("Couldn't advertise MIDI GATT application: %s" , err -> message );
456
+ g_error_free (err );
457
+ }
458
+
459
+ }
460
+
461
+ static void bluez_midi_app_advertise (
462
+ struct ba_adapter * adapter , struct bluez_midi_app * app ) {
463
+
464
+ GDBusMessage * msg ;
465
+ msg = g_dbus_message_new_method_call (BLUEZ_SERVICE , adapter -> bluez_dbus_path ,
466
+ BLUEZ_IFACE_LE_ADVERTISING_MANAGER , "RegisterAdvertisement" );
467
+
468
+ g_dbus_message_set_body (msg , g_variant_new ("(oa{sv})" , app -> path_adv , NULL ));
469
+
470
+ debug ("Registering MIDI LE advertisement: %s" , app -> path );
471
+ g_dbus_connection_send_message_with_reply (config .dbus , msg ,
472
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE , -1 , NULL , NULL ,
473
+ bluez_midi_app_advertise_finish , NULL );
474
+
475
+ g_object_unref (msg );
476
+ }
477
+
374
478
GDBusObjectManagerServer * bluez_midi_app_new (
375
479
struct ba_adapter * adapter , const char * path ) {
376
480
@@ -379,6 +483,7 @@ GDBusObjectManagerServer *bluez_midi_app_new(
379
483
return NULL ;
380
484
381
485
snprintf (app -> path , sizeof (app -> path ), "%s" , path );
486
+ snprintf (app -> path_adv , sizeof (app -> path_adv ), "%s/adv" , path );
382
487
snprintf (app -> path_service , sizeof (app -> path_service ), "%s/service" , path );
383
488
snprintf (app -> path_char , sizeof (app -> path_char ), "%s/char" , app -> path_service );
384
489
app -> hci_dev_id = adapter -> hci .dev_id ;
@@ -404,19 +509,17 @@ GDBusObjectManagerServer *bluez_midi_app_new(
404
509
g_dbus_object_manager_server_export (manager , skeleton );
405
510
g_object_unref (skeleton );
406
511
407
- g_dbus_object_manager_server_set_connection ( manager , config .dbus );
408
-
409
- GDBusMessage * msg ;
410
- msg = g_dbus_message_new_method_call ( BLUEZ_SERVICE , adapter -> bluez_dbus_path ,
411
- BLUEZ_IFACE_GATT_MANAGER , "RegisterApplication" );
512
+ if ( config .midi . advertise ) {
513
+ skeleton = bluez_midi_advertisement_skeleton_new ( app );
514
+ g_dbus_object_manager_server_export ( manager , skeleton ) ;
515
+ g_object_unref ( skeleton );
516
+ }
412
517
413
- g_dbus_message_set_body ( msg , g_variant_new ( "(oa{sv})" , path , NULL ) );
518
+ g_dbus_object_manager_server_set_connection ( manager , config . dbus );
414
519
415
- debug ("Registering MIDI GATT application: %s" , app -> path );
416
- g_dbus_connection_send_message_with_reply (config .dbus , msg ,
417
- G_DBUS_SEND_MESSAGE_FLAGS_NONE , -1 , NULL , NULL ,
418
- bluez_midi_app_register_finish , NULL );
520
+ bluez_midi_app_register (adapter , app );
521
+ if (config .midi .advertise )
522
+ bluez_midi_app_advertise (adapter , app );
419
523
420
- g_object_unref (msg );
421
524
return manager ;
422
525
}
0 commit comments