GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/devices.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 58 0.0%
Functions: 0 10 0.0%
Branches: 0 12 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/system/devices.h"
30 #include "gate/strings.h"
31 #include "gate/results.h"
32 #include "gate/platforms.h"
33 #include "gate/debugging.h"
34
35
36 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WINSTORE) && !defined(GATE_SYS_WIN16)
37 # define GATE_SYSTEM_DEVICES_WINAPI_IMPL 1
38 #elif defined(GATE_SYS_LINUX) && !defined(GATE_SYS_ANDROID)
39 # define GATE_SYSTEM_DEVICES_DBUS_IMPL 1
40 #else
41 # define GATE_SYSTEM_DEVICES_NO_IMPL 1
42 #endif
43
44
45 /* Generic implementation */
46
47 gate_result_t gate_device_entry_init(gate_device_entry_t* entry)
48 {
49 gate_mem_clear(entry, sizeof(gate_device_entry_t));
50 return GATE_RESULT_OK;
51 }
52 void gate_device_entry_release(gate_device_entry_t* entry)
53 {
54 gate_string_release(&entry->uid);
55 gate_string_release(&entry->name);
56 gate_string_release(&entry->device_class);
57 gate_string_release(&entry->device_type);
58 gate_string_release(&entry->device_path);
59 gate_string_release(&entry->hardware_id);
60 gate_string_release(&entry->mount_path);
61 }
62
63
64 struct find_bthle_device_param
65 {
66 gate_string_t const* uid;
67 gate_string_t const* address;
68 gate_device_bthle_t* device;
69 gate_result_t result;
70 };
71
72 static gate_bool_t find_bthledevice(gate_device_bthle_t const* device, void* user_param)
73 {
74 gate_bool_t ret = true; /* continue device iteration */
75 struct find_bthle_device_param* param = (struct find_bthle_device_param*)user_param;
76
77 do
78 {
79 if (param->uid)
80 {
81 if (gate_str_compare(param->uid->str, param->uid->length, device->uid, gate_str_length(device->uid)) == 0)
82 {
83 gate_mem_copy(param->device, device, sizeof(gate_device_bthle_t));
84 param->result = GATE_RESULT_OK;
85 ret = false; /* cancel further device iteration */
86 break;
87 }
88 }
89 if (param->address)
90 {
91 if (gate_str_compare(param->address->str, param->address->length, device->address, gate_str_length(device->address)) == 0)
92 {
93 gate_mem_copy(param->device, device, sizeof(gate_device_bthle_t));
94 param->result = GATE_RESULT_OK;
95 ret = false; /* cancel further device iteration */
96 break;
97 }
98 }
99 } while (0);
100
101 return ret;
102 }
103
104 gate_result_t gate_device_bthle_get(gate_string_t const* uid, gate_device_bthle_t* device)
105 {
106 gate_result_t ret;
107 struct find_bthle_device_param param;
108 gate_mem_clear(&param, sizeof(param));
109 param.uid = uid;
110 param.address = NULL;
111 param.device = device;
112 param.result = GATE_RESULT_NOMATCH;
113 ret = gate_device_bthle_enum(find_bthledevice, &param);
114 if (GATE_SUCCEEDED(ret))
115 {
116 ret = param.result;
117 }
118 return ret;
119 }
120
121 gate_result_t gate_device_bthle_get_by_address(gate_string_t const* address, gate_device_bthle_t* device)
122 {
123 gate_result_t ret;
124 struct find_bthle_device_param param;
125 gate_mem_clear(&param, sizeof(param));
126 param.uid = NULL;
127 param.address = address;
128 param.device = device;
129 param.result = GATE_RESULT_NOMATCH;
130 ret = gate_device_bthle_enum(find_bthledevice, &param);
131 if (GATE_SUCCEEDED(ret))
132 {
133 ret = param.result;
134 }
135 return ret;
136 }
137
138
139
140
141 #if defined(GATE_SYSTEM_DEVICES_WINAPI_IMPL)
142
143 /* WIN32 implementation */
144 #include "gate/system/platform/device_cfgmgr.h"
145 #include "gate/system/platform/device_winbluetooth.h"
146
147 #ifndef DIGCF_PRESENT
148 #define DIGCF_PRESENT 0x00000002
149 #endif
150
151 #ifndef DIGCF_ALLCLASSES
152 #define DIGCF_ALLCLASSES 0x00000004
153 #endif
154
155 #ifndef INVALID_HANDLE_VALUE
156 #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
157 #endif
158
159 #ifndef FALSE
160 #define FALSE 0
161 #endif
162
163 #ifndef TRUE
164 #define TRUE 1
165 #endif
166
167 static gate_result_t gate_win32_device_entries_enum(gate_device_entry_callback_t callback, void* user_param)
168 {
169 gate_result_t ret = GATE_RESULT_FAILED;
170 PVOID hDevInfo = INVALID_HANDLE_VALUE;
171 SP_DEVINFO_DATA deviceInfoData;
172 DWORD ndx;
173 gate_win32_setupapi_t const* const setupapi = gate_win32_setupapi();
174
175 do
176 {
177 if (!setupapi->SetupApiDiGetClassDevs)
178 {
179 ret = GATE_RESULT_NOTSUPPORTED;
180 break;
181 }
182
183 //gate_platform.SetupDiGetClassDevs()
184 hDevInfo = setupapi->SetupApiDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
185 if (INVALID_HANDLE_VALUE == hDevInfo)
186 {
187 ret = GATE_RESULT_FAILED;
188 break;
189 }
190
191 deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
192
193 for (ndx = 0; setupapi->SetupApiDiEnumDeviceInfo(hDevInfo, ndx, &deviceInfoData); ++ndx)
194 {
195 /*TODO*/
196 }
197
198 } while (0);
199
200 if (INVALID_HANDLE_VALUE != hDevInfo)
201 {
202 setupapi->SetupApiDiDestroyDeviceInfoList(hDevInfo);
203 }
204
205 return ret;
206 }
207
208 gate_result_t gate_device_entries_enum(unsigned entry_source, gate_device_entry_callback_t callback, void* user_param)
209 {
210 switch (entry_source)
211 {
212 case GATE_DEVICE_ENTRY_SOURCE_OS: return gate_win32_device_entries_enum(callback, user_param);
213 case GATE_DEVICE_ENTRY_SOURCE_HARDWARE: return GATE_RESULT_NOTSUPPORTED;
214 default: return GATE_RESULT_INVALIDARG;
215 }
216 }
217
218 gate_result_t gate_device_bth_enum(gate_device_bth_enum_callback callback, void* param)
219 {
220 gate_result_t ret = GATE_RESULT_OK;
221 HANDLE hfind;
222 GATE_BLUETOOTH_DEVICE_SEARCH_PARAMS btdsp;
223 GATE_BLUETOOTH_DEVICE_INFO btdi;
224 gate_device_bth_t device;
225
226 if (!load_bth_functions())
227 {
228 return GATE_RESULT_NOTSUPPORTED;
229 }
230
231 btdsp.dwSize = sizeof(btdsp);
232 btdsp.fReturnAuthenticated = TRUE;
233 btdsp.fReturnRemembered = TRUE;
234 btdsp.fReturnUnknown = TRUE;
235 btdsp.fReturnConnected = TRUE;
236 btdsp.fIssueInquiry = FALSE;
237 btdsp.cTimeoutMultiplier = 0;
238 btdsp.hRadio = NULL;
239
240 btdi.dwSize = sizeof(btdi);
241 do
242 {
243
244 hfind = gate_bth.Win32BluetoothFindFirstDevice(&btdsp, &btdi);
245 if (hfind == NULL)
246 {
247 ret = GATE_RESULT_FAILED;
248 break;
249 }
250 do
251 {
252 gate_str_print_hex_byte(&device.address[0], 2, btdi.Address.rgBytes[0], true);
253 device.address[2] = '-';
254 gate_str_print_hex_byte(&device.address[3], 2, btdi.Address.rgBytes[1], true);
255 device.address[5] = '-';
256 gate_str_print_hex_byte(&device.address[6], 2, btdi.Address.rgBytes[2], true);
257 device.address[8] = '-';
258 gate_str_print_hex_byte(&device.address[9], 2, btdi.Address.rgBytes[3], true);
259 device.address[11] = '-';
260 gate_str_print_hex_byte(&device.address[12], 2, btdi.Address.rgBytes[4], true);
261 device.address[14] = '-';
262 gate_str_print_hex_byte(&device.address[15], 2, btdi.Address.rgBytes[5], true);
263 device.address[17] = '\0';
264
265 gate_str_utf16_2_utf8(btdi.szName, gate_str16_length(btdi.szName), device.name, sizeof(device.name));
266
267 device.device_class = btdi.ulClassofDevice;
268 device.connected = btdi.fConnected;
269 device.authenticated = btdi.fAuthenticated;
270 device.last_seen = 0;
271 device.last_used = 0;
272
273 if (callback != NULL)
274 {
275 if (!callback(&device, param))
276 {
277 break;
278 }
279 }
280
281 } while (gate_bth.Win32BluetoothFindNextDevice(hfind, &btdi));
282
283 } while (0);
284
285 if (hfind != NULL)
286 {
287 gate_bth.Win32BluetoothFindDeviceClose(hfind);
288 }
289
290 return ret;
291 }
292
293
294 struct gate_bthledevice_enum_struct
295 {
296 gate_result_t result;
297 gate_device_bthle_enum_callback_t callback;
298 void* userparam;
299 };
300
301 #ifndef BLUETOOTH_GATT_FLAG_NONE
302 #define BLUETOOTH_GATT_FLAG_NONE 0x00000000
303 #endif
304
305 #ifndef BLUETOOTH_GATT_FLAG_CONNECTION_ENCRYPTED
306 #define BLUETOOTH_GATT_FLAG_CONNECTION_ENCRYPTED 0x00000001
307 #endif
308
309 #ifndef BLUETOOTH_GATT_FLAG_CONNECTION_AUTHENTICATED
310 #define BLUETOOTH_GATT_FLAG_CONNECTION_AUTHENTICATED 0x00000002
311 #endif
312
313 #ifndef BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE
314 #define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE 0x00000004
315 #endif
316
317 #ifndef BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE
318 #define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE 0x00000008
319 #endif
320
321 #ifndef BLUETOOTH_GATT_FLAG_SIGNED_WRITE
322 #define BLUETOOTH_GATT_FLAG_SIGNED_WRITE 0x00000010
323 #endif
324
325 #ifndef BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE
326 #define BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE 0x00000020
327 #endif
328
329 #ifndef BLUETOOTH_GATT_FLAG_RETURN_ALL
330 #define BLUETOOTH_GATT_FLAG_RETURN_ALL 0x00000040
331 #endif
332
333
334 static gate_bool_t gate_win32_gate_bthle_device(LPCTSTR device_path, LPCTSTR friendly_name, void* user_param)
335 {
336 struct gate_bthledevice_enum_struct* param = (struct gate_bthledevice_enum_struct*)user_param;
337 gate_bool_t ret = true;
338 gate_device_bthle_t bthle_device;
339 gate_size_t len;
340 gate_size_t pos;
341 HANDLE hfile = INVALID_HANDLE_VALUE;
342 GATE_BTH_LE_GATT_SERVICE services[256];
343 USHORT servicecount = 0;
344 HRESULT hres;
345 USHORT ndx;
346
347 gate_mem_clear(&bthle_device, sizeof(bthle_device));
348
349 do
350 {
351 gate_win32_winstr_2_utf8(friendly_name, gate_win32_winstr_length(friendly_name), bthle_device.name, sizeof(bthle_device.name));
352
353 len = gate_win32_winstr_length(device_path);
354 gate_win32_winstr_2_utf8(device_path, len, bthle_device.uid, sizeof(bthle_device.uid));
355 pos = gate_win32_winstr_char_pos_last(device_path, len, '#');
356 if (GATE_STR_NPOS != pos)
357 {
358 len = pos;
359 pos = gate_win32_winstr_char_pos_last(device_path, len, '&');
360 if (GATE_STR_NPOS != pos)
361 {
362 gate_win32_winstr_2_utf8(&device_path[pos + 1], len - pos - 1, bthle_device.address, sizeof(bthle_device.address));
363 }
364 }
365
366 if (gate_bth.Win32BluetoothGATTGetServices != NULL)
367 {
368 hfile = gate_win32_createfile(device_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
369 OPEN_EXISTING, 0, 0, NULL);
370 if (hfile != INVALID_HANDLE_VALUE)
371 {
372 //hres = gate_bth.Win32BluetoothGATTGetIncludedServices(hfile, NULL, sizeof(services) / sizeof(services[0]), services, &servicecount, BLUETOOTH_GATT_FLAG_NONE);
373 hres = gate_bth.Win32BluetoothGATTGetServices(hfile, sizeof(services) / sizeof(services[0]), services, &servicecount, BLUETOOTH_GATT_FLAG_NONE);
374 if (servicecount > sizeof(bthle_device.services) / sizeof(bthle_device.services[0]))
375 {
376 servicecount = sizeof(bthle_device.services) / sizeof(bthle_device.services[0]);
377 }
378 for (ndx = 0; ndx != servicecount; ++ndx)
379 {
380 gate_win32_winguid_to_guid(&services[ndx].ServiceUuid.Value.LongUuid, &bthle_device.services[ndx].service_guid);
381 bthle_device.services[ndx].attribute_handle = services[ndx].AttributeHandle;
382 }
383 bthle_device.service_count = servicecount;
384 }
385 }
386
387 if (param->callback != NULL)
388 {
389 ret = param->callback(&bthle_device, param->userparam);
390 }
391 } while (0);
392
393 if (hfile != INVALID_HANDLE_VALUE)
394 {
395 CloseHandle(hfile);
396 }
397
398 return ret;
399 }
400
401 gate_result_t gate_device_bthle_enum(gate_device_bthle_enum_callback_t callback, void* userparam)
402 {
403 /* GUID_BTHPORT_DEVICE_INTERFACE */
404 /*static GUID const BlueToothInterfaceGuid = { 0x0850302A, 0xB344, 0x4fda, 0x9B, 0xE9, 0x90, 0x57, 0x6B, 0x8D, 0x46, 0xF0 };*/
405
406 /* GUID_BTH_DEVICE_INTERFACE: {00F40965-E89D-4487-9890-87C3ABB211F4} */
407 /*static GUID const BlueToothInterfaceGuid = { 0x00F40965, 0xE89D, 0x4487, 0x98, 0x90, 0x87, 0xC3, 0xAB, 0xB2, 0x11, 0xF4 };*/
408
409 /* GUID_BLUETOOTHLE_DEVICE_INTERFACE {781aee18-7733-4ce4-add0-91f41c67b592} */
410 static GUID const BlueToothInterfaceGuid = { 0x781aee18, 0x7733, 0x4ce4, 0xad, 0xd0, 0x91, 0xf4, 0x1c, 0x67, 0xb5, 0x92 };
411
412 /* GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE {6e3bb679-4372-40c8-9eaa-4509df260cd8} */
413 /* static GUID const BlueToothInterfaceGuid = { 0x6e3bb679, 0x4372, 0x40c8, 0x9e, 0xaa, 0x45, 0x09, 0xdf, 0x26, 0x0c, 0xd8 }; */
414
415 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
416 struct gate_bthledevice_enum_struct bthleparam;
417
418 if (!load_bth_functions())
419 {
420 return GATE_RESULT_NOTSUPPORTED;
421 }
422
423 bthleparam.result = GATE_RESULT_OK;
424 bthleparam.callback = callback;
425 bthleparam.userparam = userparam;
426
427 ret = gate_win32_device_enum(&BlueToothInterfaceGuid, &gate_win32_gate_bthle_device, &bthleparam);
428
429 if (GATE_SUCCEEDED(ret))
430 {
431 ret = bthleparam.result;
432 }
433
434 return ret;
435 }
436
437 union gate_bthledevice_characteristic_impl
438 {
439 gate_device_bthle_characteristic_t charabase;
440 char buffer[4096];
441 };
442
443 union GATE_BTH_LE_GATT_CHARACTERISTIC_VALUE_IMPL
444 {
445 GATE_BTH_LE_GATT_CHARACTERISTIC_VALUE value;
446 char data[2048];
447 };
448
449 static void CALLBACK gate_device_bthle_service_event_cb(GATE_BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
450 {
451 GATE_DEBUG_BREAKPOINT;
452 }
453
454
455 struct bthl_svc_param
456 {
457 TCHAR device_address[32];
458 TCHAR service_path[1024];
459 HANDLE handle;
460 };
461
462 static gate_bool_t gate_device_bthle_service_enum_cb(LPCTSTR device_path, LPCTSTR friendly_name, void* user_param)
463 {
464 struct bthl_svc_param* param = (struct bthl_svc_param*)user_param;
465 gate_size_t pos = gate_win32_winstr_pos(device_path, gate_win32_winstr_length(device_path), param->device_address, gate_win32_winstr_length(param->device_address), 0);
466 if (pos != GATE_STR_NPOS)
467 {
468 do
469 {
470 /* MAC address is part of service path -> we have found the right entry */
471 param->handle = gate_win32_createfile(device_path, GENERIC_READ | GENERIC_WRITE, 0,
472 OPEN_EXISTING, 0, 0, NULL);
473 if (INVALID_HANDLE_VALUE != param->handle)
474 {
475 break;
476 }
477
478 param->handle = gate_win32_createfile(device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
479 OPEN_EXISTING, 0, 0, NULL);
480 if (INVALID_HANDLE_VALUE != param->handle)
481 {
482 break;
483 }
484
485 param->handle = gate_win32_createfile(device_path, GENERIC_READ, FILE_SHARE_READ,
486 OPEN_EXISTING, 0, 0, NULL);
487 if (INVALID_HANDLE_VALUE != param->handle)
488 {
489 break;
490 }
491
492 } while (0);
493
494 if (INVALID_HANDLE_VALUE != param->handle)
495 {
496 /* SUCCESS: cancel further iteration */
497 return false;
498 }
499
500 }
501
502 /* continue further iteration */
503 return true;
504 }
505
506 static gate_result_t bthle_resolve_service(gate_device_bthle_t const* device,
507 gate_guid_t const* service_guid,
508 GATE_BTH_LE_GATT_SERVICE* ptr_svc,
509 HANDLE* ptr_handle)
510 {
511 gate_size_t n;
512 struct bthl_svc_param service_enum_param;
513 GUID win_service_guid;
514
515 service_enum_param.handle = INVALID_HANDLE_VALUE;
516
517 gate_win32_utf8_2_winstr(device->address, gate_str_length(device->address),
518 service_enum_param.device_address,
519 sizeof(service_enum_param.device_address) / sizeof(service_enum_param.device_address[0])
520 );
521 gate_win32_guid_to_winguid(service_guid, &win_service_guid);
522 if ((win_service_guid.Data2 == 0) && (win_service_guid.Data3 == 0))
523 {
524 /* simple GUID / SHORT-UID -> patch with default suffix "...-0000-1000-8000-00805f9b34fb" */
525 win_service_guid.Data3 = 0x1000;
526 win_service_guid.Data4[0] = 0x80;
527 win_service_guid.Data4[1] = 0x00;
528 win_service_guid.Data4[2] = 0x00;
529 win_service_guid.Data4[3] = 0x80;
530 win_service_guid.Data4[4] = 0x5f;
531 win_service_guid.Data4[5] = 0x9b;
532 win_service_guid.Data4[6] = 0x34;
533 win_service_guid.Data4[7] = 0xfb;
534 }
535 gate_win32_device_enum(&win_service_guid, &gate_device_bthle_service_enum_cb, &service_enum_param);
536
537 if (service_enum_param.handle == INVALID_HANDLE_VALUE)
538 {
539 return GATE_RESULT_NOTAVAILABLE;
540 }
541
542 //ptr_svc->AttributeHandle = service->attribute_handle;
543 gate_win32_guid_to_winguid(service_guid, &ptr_svc->ServiceUuid.Value.LongUuid);
544 ptr_svc->ServiceUuid.IsShortUuid = (ptr_svc->ServiceUuid.Value.LongUuid.Data2 == 0) && (ptr_svc->ServiceUuid.Value.LongUuid.Data3 == 0)
545 ? TRUE
546 : FALSE;
547
548 *ptr_handle = service_enum_param.handle;
549
550 for (n = 0; n != device->service_count; ++n)
551 {
552 if (gate_guid_equals(service_guid, &device->services[n].service_guid))
553 {
554 ptr_svc->AttributeHandle = device->services[n].attribute_handle;
555 return GATE_RESULT_OK;
556 }
557 }
558 return GATE_RESULT_NOMATCH;
559 }
560
561
562 static gate_result_t bthle_build_characteristic(HANDLE svc_handle, GATE_BTH_LE_GATT_CHARACTERISTIC* src,
563 union gate_bthledevice_characteristic_impl* dst)
564 {
565 gate_result_t ret = GATE_RESULT_FAILED;
566 GATE_BLUETOOTH_GATT_EVENT_HANDLE event_handle = NULL;
567 GATE_BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION event_parameter_in;
568 GATE_BTH_LE_GATT_EVENT_TYPE event_type = Gate_CharacteristicValueChangedEvent;
569 union GATE_BTH_LE_GATT_CHARACTERISTIC_VALUE_IMPL characteristic_value;
570 USHORT value_length = 0;
571 HRESULT hr;
572
573 gate_mem_clear(dst, sizeof(gate_device_bthle_characteristic_t));
574
575 do
576 {
577 /*
578 descriptorcount = sizeof(descriptors) / sizeof(descriptors[0]);
579 hr = gate_bth.Win32BluetoothGATTGetDescriptors(hfile, &charas[ndx], descriptorcount, &descriptors[0], &descriptorcount, 0);
580
581 if(SUCCEEDED(hr))
582 {
583 for(descr_ndx = 0; descr_ndx != descriptorcount; ++descr_ndx)
584 {
585 hr = gate_bth.Win32BluetoothGATTGetDescriptorValue(hfile, &descriptors[descr_ndx],
586 sizeof(buffer), ptr_descr_value, NULL, BLUETOOTH_GATT_FLAG_NONE);
587 if(SUCCEEDED(hr))
588 {
589 }
590 }
591 }
592 */
593
594 if (src->IsNotifiable)
595 {
596 event_parameter_in.NumCharacteristics = 1;
597 event_parameter_in.Characteristics[0] = *src;
598
599 hr = gate_bth.Win32BluetoothGATTRegisterEvent(svc_handle, event_type, &event_parameter_in,
600 (PGATE_FNBLUETOOTH_GATT_EVENT_CALLBACK)&gate_device_bthle_service_event_cb, NULL, &event_handle, BLUETOOTH_GATT_FLAG_NONE);
601 if (FAILED(hr))
602 {
603 break;
604 }
605 }
606
607 if (src->IsReadable)
608 {
609 gate_win32_winguid_to_guid(&src->CharacteristicUuid.Value.LongUuid, &dst->charabase.characteristic_guid);
610
611 hr = gate_bth.Win32BluetoothGATTGetCharacteristicValue(svc_handle, src, 0, NULL, &value_length,
612 BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE);
613
614 characteristic_value.value.DataSize = sizeof(characteristic_value);
615
616 hr = gate_bth.Win32BluetoothGATTGetCharacteristicValue(svc_handle, src, sizeof(characteristic_value),
617 &characteristic_value.value, &value_length,
618 BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE);
619 if (FAILED(hr))
620 {
621 hr = gate_bth.Win32BluetoothGATTGetCharacteristicValue(svc_handle, src, sizeof(characteristic_value),
622 &characteristic_value.value, &value_length,
623 BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE);
624 }
625 if (FAILED(hr))
626 {
627 ret = GATE_RESULT_FAILED;
628 break;
629 }
630 dst->charabase.flags |= GATE_DEVICE_BTHLE_FLAG_READABLE;
631 dst->charabase.data_length = characteristic_value.value.DataSize;
632 if (dst->charabase.data_length > sizeof(dst->buffer) - sizeof(dst->charabase))
633 {
634 /* reduce size of data to internal buffer */
635 dst->charabase.data_length = sizeof(dst->buffer) - sizeof(dst->charabase);
636 }
637 if (dst->charabase.data_length > 0)
638 {
639 gate_mem_copy(&dst->charabase.data[0], &characteristic_value.value.Data[0], dst->charabase.data_length);
640 }
641 }
642
643 if (src->IsWritable || src->IsWritableWithoutResponse)
644 {
645 dst->charabase.flags |= GATE_DEVICE_BTHLE_FLAG_WRITABLE;
646 }
647
648 ret = GATE_RESULT_OK;
649
650 } while (0);
651
652 if (event_handle != NULL)
653 {
654 gate_bth.Win32BluetoothGATTUnregisterEvent(event_handle, BLUETOOTH_GATT_FLAG_NONE);
655 }
656
657 return ret;
658
659 }
660
661
662
663 gate_result_t gate_device_bthle_service_enum(gate_device_bthle_t const* device, gate_device_bthle_service_t const* service,
664 gate_device_bthle_service_enum_callback_t callback, void* user_param)
665 {
666 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
667 gate_result_t result;
668 GATE_BTH_LE_GATT_SERVICE svc;
669 HANDLE svc_handle = INVALID_HANDLE_VALUE;
670 GATE_BTH_LE_GATT_CHARACTERISTIC charas[128];
671 USHORT characount = sizeof(charas) / sizeof(charas[0]);
672 union gate_bthledevice_characteristic_impl gate_chara;
673 USHORT ndx;
674 HRESULT hr;
675
676 do
677 {
678 if (!load_bth_functions())
679 {
680 ret = GATE_RESULT_NOTSUPPORTED;
681 break;
682 }
683
684 ret = bthle_resolve_service(device, &service->service_guid, &svc, &svc_handle);
685 GATE_BREAK_IF_FAILED(ret);
686 hr = gate_bth.Win32BluetoothGATTGetCharacteristics(svc_handle, &svc, characount, &charas[0], &characount, BLUETOOTH_GATT_FLAG_NONE);
687 if (FAILED(hr))
688 {
689 ret = GATE_RESULT_FAILED;
690 break;
691 }
692
693 ret = GATE_RESULT_OK;
694
695 for (ndx = 0; ndx != characount; ++ndx)
696 {
697 gate_mem_clear(&gate_chara, sizeof(gate_chara));
698
699 result = bthle_build_characteristic(svc_handle, &charas[ndx], &gate_chara);
700 if (GATE_FAILED(result))
701 {
702 continue;
703 }
704
705 if (callback != NULL)
706 {
707 if (!callback(&gate_chara.charabase, user_param))
708 {
709 ret = GATE_RESULT_CANCELED;
710 break;
711 }
712 }
713 }
714 ret = GATE_RESULT_OK;
715 } while (0);
716
717 if (svc_handle != INVALID_HANDLE_VALUE)
718 {
719 CloseHandle(svc_handle);
720 }
721
722 return ret;
723 }
724
725
726 gate_result_t gate_device_bthle_characteristic_get(gate_device_bthle_t const* device,
727 gate_guid_t const* service_guid,
728 gate_guid_t const* characteristic_guid,
729 char* buffer,
730 gate_size_t* buffer_len)
731 {
732 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
733 gate_guid_t current_chara_guid;
734 GATE_BTH_LE_GATT_SERVICE svc;
735 HANDLE svc_handle = INVALID_HANDLE_VALUE;
736 GATE_BTH_LE_GATT_CHARACTERISTIC charas[128];
737 USHORT characount = sizeof(charas) / sizeof(charas[0]);
738 union gate_bthledevice_characteristic_impl gate_chara;
739 USHORT ndx;
740 HRESULT hr;
741
742 do
743 {
744 if (!load_bth_functions())
745 {
746 ret = GATE_RESULT_NOTSUPPORTED;
747 break;
748 }
749 if (!buffer_len)
750 {
751 ret = GATE_RESULT_INVALIDARG;
752 break;
753 }
754
755 ret = bthle_resolve_service(device, service_guid, &svc, &svc_handle);
756 GATE_BREAK_IF_FAILED(ret);
757
758 hr = gate_bth.Win32BluetoothGATTGetCharacteristics(svc_handle, &svc, characount, &charas[0], &characount, BLUETOOTH_GATT_FLAG_NONE);
759 if (FAILED(hr))
760 {
761 ret = GATE_RESULT_FAILED;
762 break;
763 }
764
765 ret = GATE_RESULT_NOMATCH;
766 for (ndx = 0; ndx != characount; ++ndx)
767 {
768 gate_win32_winguid_to_guid(&charas[ndx].CharacteristicUuid.Value.LongUuid, &current_chara_guid);
769 if (gate_guid_equals(&current_chara_guid, characteristic_guid))
770 {
771 gate_mem_clear(&gate_chara, sizeof(gate_chara));
772 ret = bthle_build_characteristic(svc_handle, &charas[ndx], &gate_chara);
773 GATE_BREAK_IF_FAILED(ret);
774
775 if (!buffer)
776 {
777 /* just return the size of the value */
778 *buffer_len = gate_chara.charabase.data_length;
779 }
780 else
781 {
782 if (*buffer_len > gate_chara.charabase.data_length)
783 {
784 *buffer_len = gate_chara.charabase.data_length;
785 }
786 if (*buffer_len > 0)
787 {
788 gate_mem_copy(buffer, gate_chara.charabase.data, *buffer_len);
789 }
790 }
791 break;
792 }
793 }
794 } while (0);
795
796 if (svc_handle != INVALID_HANDLE_VALUE)
797 {
798 CloseHandle(svc_handle);
799 }
800
801 return ret;
802 }
803
804 GATE_SYSTEM_API gate_result_t gate_device_bthle_characteristic_set(gate_device_bthle_t const* device,
805 gate_guid_t const* service_guid,
806 gate_guid_t const* characteristic_guid,
807 char const* buffer,
808 gate_size_t buffer_len)
809 {
810 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
811 gate_guid_t current_chara_guid;
812 GATE_BTH_LE_GATT_SERVICE svc;
813 HANDLE svc_handle = INVALID_HANDLE_VALUE;
814 GATE_BTH_LE_GATT_CHARACTERISTIC charas[128];
815 USHORT characount = sizeof(charas) / sizeof(charas[0]);
816 USHORT ndx;
817 HRESULT hr;
818 ULONG64 rel_context = 0;
819 union GATE_BTH_LE_GATT_CHARACTERISTIC_VALUE_IMPL value;
820
821 do
822 {
823 if (!load_bth_functions())
824 {
825 ret = GATE_RESULT_NOTSUPPORTED;
826 break;
827 }
828 if (!buffer_len)
829 {
830 ret = GATE_RESULT_INVALIDARG;
831 break;
832 }
833
834 if (buffer_len > (sizeof(value.data) - sizeof(value.value)))
835 {
836 ret = GATE_RESULT_BUFFERTOOSMALL;
837 break;
838 }
839
840 gate_mem_copy(&value.value.Data[0], buffer, buffer_len);
841 value.value.DataSize = (ULONG)buffer_len;
842
843 ret = bthle_resolve_service(device, service_guid, &svc, &svc_handle);
844 GATE_BREAK_IF_FAILED(ret);
845
846 hr = gate_bth.Win32BluetoothGATTGetCharacteristics(svc_handle, &svc, characount, &charas[0], &characount, BLUETOOTH_GATT_FLAG_NONE);
847 if (FAILED(hr))
848 {
849 ret = GATE_RESULT_FAILED;
850 break;
851 }
852
853 ret = GATE_RESULT_NOMATCH;
854 for (ndx = 0; ndx != characount; ++ndx)
855 {
856 gate_win32_winguid_to_guid(&charas[ndx].CharacteristicUuid.Value.LongUuid, &current_chara_guid);
857 if (gate_guid_equals(&current_chara_guid, characteristic_guid))
858 {
859 if (!charas[ndx].IsWritable)
860 {
861 ret = GATE_RESULT_ACCESSDENIED;
862 break;
863 }
864
865 hr = gate_bth.Win32BluetoothGATTSetCharacteristicValue(svc_handle, &charas[ndx], &value.value, rel_context, BLUETOOTH_GATT_FLAG_NONE);
866 if (FAILED(hr))
867 {
868 ret = GATE_RESULT_FAILED;
869 }
870 else
871 {
872 ret = GATE_RESULT_OK;
873 }
874 break;
875 }
876 }
877 } while (0);
878
879 if (svc_handle != INVALID_HANDLE_VALUE)
880 {
881 CloseHandle(svc_handle);
882 }
883
884 return ret;
885 }
886
887 #endif /* GATE_SYSTEM_DEVICES_WINAPI_IMPL */
888
889
890 #if defined(GATE_SYSTEM_DEVICES_DBUS_IMPL)
891
892 #include "gate/system/platform/linux_dbus_api.h"
893
894 gate_result_t gate_device_bth_enum(gate_device_bth_enum_callback callback, void* userparam)
895 {
896 (void)callback;
897 (void)userparam;
898 return GATE_RESULT_NOTIMPLEMENTED;
899 }
900
901 gate_result_t gate_device_bthle_enum(gate_device_bthle_enum_callback_t callback, void* userparam)
902 {
903 (void)callback;
904 (void)userparam;
905 return GATE_RESULT_NOTIMPLEMENTED;
906 }
907
908 gate_result_t gate_device_bthle_service_enum(gate_device_bthle_t const* device,
909 gate_device_bthle_service_t const* service,
910 gate_device_bthle_service_enum_callback_t callback, void* userparam)
911 {
912 (void)device;
913 (void)service;
914 (void)callback;
915 (void)userparam;
916 return GATE_RESULT_NOTIMPLEMENTED;
917 }
918
919 gate_result_t gate_device_bthle_characteristic_get(gate_device_bthle_t const* device,
920 gate_guid_t const* service_guid,
921 gate_guid_t const* characteristic_guid,
922 char* buffer,
923 gate_size_t* buffer_len)
924 {
925 (void)device;
926 (void)service_guid;
927 (void)characteristic_guid;
928 (void)buffer;
929 (void)buffer_len;
930 return GATE_RESULT_NOTIMPLEMENTED;
931 }
932
933 gate_result_t gate_device_bthle_characteristic_set(gate_device_bthle_t const* device,
934 gate_guid_t const* service_guid,
935 gate_guid_t const* characteristic_guid,
936 char const* buffer,
937 gate_size_t buffer_len)
938 {
939 (void)device;
940 (void)service_guid;
941 (void)characteristic_guid;
942 (void)buffer;
943 (void)buffer_len;
944 return GATE_RESULT_NOTIMPLEMENTED;
945 }
946
947 #endif /* GATE_SYSTEM_DEVICES_DBUS_IMPL */
948
949
950
951 #if defined(GATE_SYSTEM_DEVICES_NO_IMPL)
952
953
954 gate_result_t gate_device_bth_enum(gate_device_bth_enum_callback callback, void* userparam)
955 {
956 (void)callback;
957 (void)userparam;
958 return GATE_RESULT_NOTIMPLEMENTED;
959 }
960
961 gate_result_t gate_device_bthle_enum(gate_device_bthle_enum_callback_t callback, void* userparam)
962 {
963 (void)callback;
964 (void)userparam;
965 return GATE_RESULT_NOTIMPLEMENTED;
966 }
967
968 gate_result_t gate_device_bthle_service_enum(gate_device_bthle_t const* device,
969 gate_device_bthle_service_t const* service,
970 gate_device_bthle_service_enum_callback_t callback, void* userparam)
971 {
972 (void)device;
973 (void)service;
974 (void)callback;
975 (void)userparam;
976 return GATE_RESULT_NOTIMPLEMENTED;
977 }
978
979 gate_result_t gate_device_bthle_characteristic_get(gate_device_bthle_t const* device,
980 gate_guid_t const* service_guid,
981 gate_guid_t const* characteristic_guid,
982 char* buffer,
983 gate_size_t* buffer_len)
984 {
985 (void)device;
986 (void)service_guid;
987 (void)characteristic_guid;
988 (void)buffer;
989 (void)buffer_len;
990 return GATE_RESULT_NOTIMPLEMENTED;
991 }
992
993 gate_result_t gate_device_bthle_characteristic_set(gate_device_bthle_t const* device,
994 gate_guid_t const* service_guid,
995 gate_guid_t const* characteristic_guid,
996 char const* buffer,
997 gate_size_t buffer_len)
998 {
999 (void)device;
1000 (void)service_guid;
1001 (void)characteristic_guid;
1002 (void)buffer;
1003 (void)buffer_len;
1004 return GATE_RESULT_NOTIMPLEMENTED;
1005 }
1006
1007
1008 #endif /* GATE_SYSTEM_DEVICES_NO_IMPL */
1009