summaryrefslogtreecommitdiffstats
path: root/src/detection/bluetooth/bluetooth_apple.m
blob: 9cbf732a50ff236120bab68d8707bd26bb41e639 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "bluetooth.h"

#import <IOBluetooth/IOBluetooth.h>

@interface IOBluetoothDevice()
    @property (nonatomic) uint8_t batteryPercentCase;
    @property (nonatomic) uint8_t batteryPercentCombined;
    @property (nonatomic) uint8_t batteryPercentLeft;
    @property (nonatomic) uint8_t batteryPercentRight;
    @property (nonatomic) uint8_t batteryPercentSingle;
@end

const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
    NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
    if(!ioDevices)
        return "IOBluetoothDevice.pairedDevices failed";

    for(IOBluetoothDevice* ioDevice in ioDevices)
    {
        if (!options->showDisconnected && !ioDevice.isConnected)
            continue;

        FFBluetoothResult* device = FF_LIST_ADD(FFBluetoothResult, *devices);
        ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
        ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
        ffStrbufReplaceAllC(&device->address, '-', ':');
        ffStrbufUpperCase(&device->address);
        ffStrbufInit(&device->type);

        if (ioDevice.batteryPercentSingle)
            device->battery = ioDevice.batteryPercentSingle;
        else if (ioDevice.batteryPercentCombined)
            device->battery = ioDevice.batteryPercentCombined;
        else if (ioDevice.batteryPercentCase)
            device->battery = ioDevice.batteryPercentCase;

        device->connected = !!ioDevice.isConnected;
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
            ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved1)
            ffStrbufAppendS(&device->type, "LE audio, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved2)
            ffStrbufAppendS(&device->type, "Reserved for future use, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorPositioning)
            ffStrbufAppendS(&device->type, "Positioning, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorNetworking)
            ffStrbufAppendS(&device->type, "Networking, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorRendering)
            ffStrbufAppendS(&device->type, "Rendering, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorCapturing)
            ffStrbufAppendS(&device->type, "Capturing, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorObjectTransfer)
            ffStrbufAppendS(&device->type, "Object Transfer, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorAudio)
            ffStrbufAppendS(&device->type, "Audio, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorTelephony)
            ffStrbufAppendS(&device->type, "Telephony, ");
        if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorInformation)
            ffStrbufAppendS(&device->type, "Information, ");

        if(device->type.length == 0)
        {
            switch(ioDevice.deviceClassMajor)
            {
                case kBluetoothDeviceClassMajorMiscellaneous:
                    ffStrbufAppendS(&device->type, "Miscellaneous");
                    break;
                case kBluetoothDeviceClassMajorComputer:
                    ffStrbufAppendS(&device->type, "Computer");
                    break;
                case kBluetoothDeviceClassMajorPhone:
                    ffStrbufAppendS(&device->type, "Phone");
                    break;
                case kBluetoothDeviceClassMajorLANAccessPoint:
                    ffStrbufAppendS(&device->type, "LAN/Network Access point");
                    break;
                case kBluetoothDeviceClassMajorAudio:
                    ffStrbufAppendS(&device->type, "Audio/Video");
                    break;
                case kBluetoothDeviceClassMajorPeripheral:
                    ffStrbufAppendS(&device->type, "Peripheral");
                    break;
                case kBluetoothDeviceClassMajorImaging:
                    ffStrbufAppendS(&device->type, "Imaging");
                    break;
                case kBluetoothDeviceClassMajorWearable:
                    ffStrbufAppendS(&device->type, "Wearable");
                    break;
                case kBluetoothDeviceClassMajorToy:
                    ffStrbufAppendS(&device->type, "Toy");
                    break;
                case kBluetoothDeviceClassMajorHealth:
                    ffStrbufAppendS(&device->type, "Health");
                    break;
                case kBluetoothDeviceClassMajorUnclassified:
                    ffStrbufAppendS(&device->type, "Uncategorized");
                    break;
                default:
                    ffStrbufAppendS(&device->type, "Unknown");
                    break;
            }
        }
        else
        {
            ffStrbufTrimRight(&device->type, ' ');
            ffStrbufTrimRight(&device->type, ',');
        }
    }

    return NULL;
}