Unverified Commit 78821469 authored by Kevin's avatar Kevin Committed by GitHub
Browse files

Merge pull request #2 from hybridgroup/feature/osx-highsierra

Premininary support for OS X High Sierra
parents 607987fe bb999a2c
......@@ -68,7 +68,7 @@ func (cln *Client) DiscoverProfile(force bool) (*ble.Profile, error) {
// DiscoverServices finds all the primary services on a server. [Vol 3, Part G, 4.4.1]
// If filter is specified, only filtered services are returned.
func (cln *Client) DiscoverServices(ss []ble.UUID) ([]*ble.Service, error) {
rsp := cln.conn.sendReq(45, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdDiscoverServices], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgUUIDs": uuidSlice(ss),
})
......@@ -93,7 +93,7 @@ func (cln *Client) DiscoverServices(ss []ble.UUID) ([]*ble.Service, error) {
// DiscoverIncludedServices finds the included services of a service. [Vol 3, Part G, 4.5.1]
// If filter is specified, only filtered services are returned.
func (cln *Client) DiscoverIncludedServices(ss []ble.UUID, s *ble.Service) ([]*ble.Service, error) {
rsp := cln.conn.sendReq(60, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdDiscoverIncludedServices], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgServiceStartHandle": s.Handle,
"kCBMsgArgServiceEndHandle": s.EndHandle,
......@@ -108,7 +108,7 @@ func (cln *Client) DiscoverIncludedServices(ss []ble.UUID, s *ble.Service) ([]*b
// DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1]
// If filter is specified, only filtered characteristics are returned.
func (cln *Client) DiscoverCharacteristics(cs []ble.UUID, s *ble.Service) ([]*ble.Characteristic, error) {
rsp := cln.conn.sendReq(62, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdDiscoverCharacteristics], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgServiceStartHandle": s.Handle,
"kCBMsgArgServiceEndHandle": s.EndHandle,
......@@ -132,7 +132,7 @@ func (cln *Client) DiscoverCharacteristics(cs []ble.UUID, s *ble.Service) ([]*bl
// DiscoverDescriptors finds all the descriptors within a characteristic. [Vol 3, Part G, 4.7.1]
// If filter is specified, only filtered descriptors are returned.
func (cln *Client) DiscoverDescriptors(ds []ble.UUID, c *ble.Characteristic) ([]*ble.Descriptor, error) {
rsp := cln.conn.sendReq(70, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdDiscoverDescriptors], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgCharacteristicHandle": c.Handle,
"kCBMsgArgCharacteristicValueHandle": c.ValueHandle,
......@@ -150,7 +150,7 @@ func (cln *Client) DiscoverDescriptors(ds []ble.UUID, c *ble.Characteristic) ([]
// ReadCharacteristic reads a characteristic value from a server. [Vol 3, Part G, 4.8.1]
func (cln *Client) ReadCharacteristic(c *ble.Characteristic) ([]byte, error) {
rsp := cln.conn.sendReq(65, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdReadCharacteristic], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgCharacteristicHandle": c.Handle,
"kCBMsgArgCharacteristicValueHandle": c.ValueHandle,
......@@ -176,15 +176,15 @@ func (cln *Client) WriteCharacteristic(c *ble.Characteristic, b []byte, noRsp bo
"kCBMsgArgType": map[bool]int{false: 0, true: 1}[noRsp],
}
if noRsp {
cln.conn.sendCmd(66, args)
cln.conn.sendCmd(xpcID[cmdWriteCharacteristic], args)
return nil
}
return cln.conn.sendReq(66, args).err()
return cln.conn.sendReq(xpcID[cmdWriteCharacteristic], args).err()
}
// ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1]
func (cln *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) {
rsp := cln.conn.sendReq(77, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdReadDescriptor], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgDescriptorHandle": d.Handle,
})
......@@ -196,7 +196,7 @@ func (cln *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) {
// WriteDescriptor writes a characteristic descriptor to a server. [Vol 3, Part G, 4.12.3]
func (cln *Client) WriteDescriptor(d *ble.Descriptor, b []byte) error {
rsp := cln.conn.sendReq(78, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdWriteDescriptor], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgDescriptorHandle": d.Handle,
"kCBMsgArgData": b,
......@@ -206,7 +206,7 @@ func (cln *Client) WriteDescriptor(d *ble.Descriptor, b []byte) error {
// ReadRSSI retrieves the current RSSI value of remote peripheral. [Vol 2, Part E, 7.5.4]
func (cln *Client) ReadRSSI() int {
rsp := cln.conn.sendReq(44, xpc.Dict{"kCBMsgArgDeviceUUID": cln.id})
rsp := cln.conn.sendReq(xpcID[cmdReadRSSI], xpc.Dict{"kCBMsgArgDeviceUUID": cln.id})
if rsp.err() != nil {
return 0
}
......@@ -226,7 +226,7 @@ func (cln *Client) Subscribe(c *ble.Characteristic, ind bool, fn ble.Notificatio
cln.conn.Lock()
defer cln.conn.Unlock()
cln.conn.subs[c.Handle] = &sub{fn: fn, char: c}
rsp := cln.conn.sendReq(68, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdSubscribeCharacteristic], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgCharacteristicHandle": c.Handle,
"kCBMsgArgCharacteristicValueHandle": c.ValueHandle,
......@@ -242,7 +242,7 @@ func (cln *Client) Subscribe(c *ble.Characteristic, ind bool, fn ble.Notificatio
// Unsubscribe unsubscribes to indication (if ind is set true), or notification
// of a specified characteristic value. [Vol 3, Part G, 4.10 & 4.11]
func (cln *Client) Unsubscribe(c *ble.Characteristic, ind bool) error {
rsp := cln.conn.sendReq(68, xpc.Dict{
rsp := cln.conn.sendReq(xpcID[cmdSubscribeCharacteristic], xpc.Dict{
"kCBMsgArgDeviceUUID": cln.id,
"kCBMsgArgCharacteristicHandle": c.Handle,
"kCBMsgArgCharacteristicValueHandle": c.ValueHandle,
......@@ -267,7 +267,7 @@ func (cln *Client) ClearSubscriptions() error {
// CancelConnection disconnects the connection.
func (cln *Client) CancelConnection() error {
rsp := cln.conn.sendReq(32, xpc.Dict{"kCBMsgArgDeviceUUID": cln.id})
rsp := cln.conn.sendReq(xpcID[cmdDisconnect], xpc.Dict{"kCBMsgArgDeviceUUID": cln.id})
return rsp.err()
}
......
......@@ -102,7 +102,7 @@ func (c *conn) subscribed(char *ble.Characteristic) {
return
}
send := func(b []byte) (int, error) {
c.dev.sendCmd(c.dev.pm, 15, xpc.Dict{
c.dev.sendCmd(c.dev.pm, xpcID[cmdSubscribed], xpc.Dict{
"kCBMsgArgUUIDs": [][]byte{},
"kCBMsgArgAttributeID": h,
"kCBMsgArgData": b,
......
......@@ -15,35 +15,6 @@ import (
"sync"
)
const (
evtStateChanged = 4
evtStateChangedPreHighSierra = 6
evtAdvertisingStarted = 16
evtAdvertisingStopped = 17
evtServiceAdded = 18
evtReadRequest = 19
evtWriteRequest = 20
evtSubscribe = 21
evtUnubscribe = 22
evtConfirmation = 23
evtPeripheralDiscovered = 37
evtPeripheralConnected = 38
evtPeripheralDisconnected = 40
evtATTMTU = 53
evtRSSIRead = 55
evtServiceDiscovered = 56
evtIncludedServicesDiscovered = 63
evtCharacteristicsDiscovered = 64
evtCharacteristicRead = 71
evtCharacteristicWritten = 72
evtNotificationValueSet = 74
evtDescriptorsDiscovered = 76
evtDescriptorRead = 79
evtDescriptorWritten = 80
evtSleveConnectionComplete = 81
evtMasterConnectionComplete = 82
)
// Device is either a Peripheral or Central device.
type Device struct {
pm xpc.XPC // peripheralManager
......@@ -67,6 +38,10 @@ type Device struct {
// NewDevice returns a BLE device.
func NewDevice(opts ...Option) (*Device, error) {
initXpcIDs()
var utsname xpc.Utsname
xpc.Uname(&utsname)
d := &Device{
rspc: make(chan msg),
conns: make(map[string]*conn),
......@@ -78,8 +53,15 @@ func NewDevice(opts ...Option) (*Device, error) {
return nil, err
}
d.pm = xpc.XpcConnect("com.apple.blued", d)
d.cm = xpc.XpcConnect("com.apple.blued", d)
if utsname.Release < "17." {
// yosemite
d.pm = xpc.XpcConnect("com.apple.blued", d)
d.cm = xpc.XpcConnect("com.apple.blued", d)
} else {
// high sierra
d.pm = xpc.XpcConnect("com.apple.bluetoothd", d)
d.cm = xpc.XpcConnect("com.apple.bluetoothd", d)
}
return d, errors.Wrap(d.Init(), "can't init")
}
......@@ -95,7 +77,7 @@ func (d *Device) Option(opts ...Option) error {
// Init ...
func (d *Device) Init() error {
rsp := d.sendReq(d.cm, 1, xpc.Dict{
rsp := d.sendReq(d.cm, xpcID[cmdInit], xpc.Dict{
"kCBMsgArgName": fmt.Sprintf("gopher-%v", time.Now().Unix()),
"kCBMsgArgOptions": xpc.Dict{
"kCBInitOptionShowPowerAlert": 1,
......@@ -107,7 +89,7 @@ func (d *Device) Init() error {
return fmt.Errorf("state: %s", s)
}
rsp = d.sendReq(d.pm, 1, xpc.Dict{
rsp = d.sendReq(d.pm, xpcID[cmdInit], xpc.Dict{
"kCBMsgArgName": fmt.Sprintf("gopher-%v", time.Now().Unix()),
"kCBMsgArgOptions": xpc.Dict{
"kCBInitOptionShowPowerAlert": 1,
......@@ -123,7 +105,7 @@ func (d *Device) Init() error {
// Advertise advertises the given Advertisement
func (d *Device) Advertise(ctx context.Context, adv ble.Advertisement) error {
if err := d.sendReq(d.pm, 8, xpc.Dict{
if err := d.sendReq(d.pm, xpcID[cmdAdvertiseStart], xpc.Dict{
"kCBAdvDataLocalName": adv.LocalName(),
"kCBAdvDataServiceUUIDs": adv.Services(),
"kCBAdvDataAppleMfgData": adv.ManufacturerData(),
......@@ -140,7 +122,7 @@ func (d *Device) Advertise(ctx context.Context, adv ble.Advertisement) error {
func (d *Device) AdvertiseMfgData(ctx context.Context, id uint16, md []byte) error {
l := len(md)
b := []byte{byte(l + 3), 0xFF, uint8(id), uint8(id >> 8)}
if err := d.sendReq(d.pm, 8, xpc.Dict{
if err := d.sendReq(d.pm, xpcID[cmdAdvertiseStart], xpc.Dict{
"kCBAdvDataAppleMfgData": append(b, md...),
}).err(); err != nil {
return errors.Wrap(err, "can't advertise")
......@@ -156,7 +138,7 @@ func (d *Device) AdvertiseServiceData16(ctx context.Context, id uint16, b []byte
0x03, 0x03, uint8(id), uint8(id >> 8),
byte(l + 3), 0x16, uint8(id), uint8(id >> 8),
}
if err := d.sendReq(d.pm, 8, xpc.Dict{
if err := d.sendReq(d.pm, xpcID[cmdAdvertiseStart], xpc.Dict{
"kCBAdvDataAppleMfgData": append(prefix, b...),
}).err(); err != nil {
return errors.Wrap(err, "can't advertise")
......@@ -167,7 +149,7 @@ func (d *Device) AdvertiseServiceData16(ctx context.Context, id uint16, b []byte
// AdvertiseNameAndServices advertises name and specifid service UUIDs.
func (d *Device) AdvertiseNameAndServices(ctx context.Context, name string, ss ...ble.UUID) error {
if err := d.sendReq(d.pm, 8, xpc.Dict{
if err := d.sendReq(d.pm, xpcID[cmdAdvertiseStart], xpc.Dict{
"kCBAdvDataLocalName": name,
"kCBAdvDataServiceUUIDs": uuidSlice(ss)},
).err(); err != nil {
......@@ -187,7 +169,7 @@ func (d *Device) AdvertiseIBeaconData(ctx context.Context, md []byte) error {
ibeaconCode := []byte{0x02, 0x15}
return d.AdvertiseMfgData(ctx, 0x004C, append(ibeaconCode, md...))
}
if err := d.sendReq(d.pm, 8, xpc.Dict{"kCBAdvDataAppleBeaconKey": md}).err(); err != nil {
if err := d.sendReq(d.pm, xpcID[cmdAdvertiseStart], xpc.Dict{"kCBAdvDataAppleBeaconKey": md}).err(); err != nil {
return err
}
<-ctx.Done()
......@@ -206,13 +188,13 @@ func (d *Device) AdvertiseIBeacon(ctx context.Context, u ble.UUID, major, minor
// stopAdvertising stops advertising.
func (d *Device) stopAdvertising() error {
return errors.Wrap(d.sendReq(d.pm, 9, nil).err(), "can't stop advertising")
return errors.Wrap(d.sendReq(d.pm, xpcID[cmdAdvertiseStop], nil).err(), "can't stop advertising")
}
// Scan ...
func (d *Device) Scan(ctx context.Context, allowDup bool, h ble.AdvHandler) error {
d.advHandler = h
if err := d.sendCmd(d.cm, 29, xpc.Dict{
if err := d.sendCmd(d.cm, xpcID[cmdScanningStart], xpc.Dict{
// "kCBMsgArgUUIDs": uuidSlice(ss),
"kCBMsgArgOptions": xpc.Dict{
"kCBScanOptionAllowDuplicates": map[bool]int{true: 1, false: 0}[allowDup],
......@@ -229,12 +211,12 @@ func (d *Device) Scan(ctx context.Context, allowDup bool, h ble.AdvHandler) erro
// stopAdvertising stops advertising.
func (d *Device) stopScanning() error {
return errors.Wrap(d.sendCmd(d.cm, 30, nil), "can't stop scanning")
return errors.Wrap(d.sendCmd(d.cm, xpcID[cmdScanningStop], nil), "can't stop scanning")
}
// RemoveAllServices removes all services of device's
func (d *Device) RemoveAllServices() error {
return d.sendCmd(d.pm, 12, nil)
return d.sendCmd(d.pm, xpcID[cmdServicesRemove], nil)
}
// AddService adds a service to device's database.
......@@ -335,7 +317,7 @@ func (d *Device) AddService(s *ble.Service) error {
}
xs["kCBMsgArgCharacteristics"] = xcs
return d.sendReq(d.pm, 10, xs).err()
return d.sendReq(d.pm, xpcID[cmdServicesAdd], xs).err()
}
// SetServices ...
......@@ -353,7 +335,7 @@ func (d *Device) SetServices(ss []*ble.Service) error {
// Dial ...
func (d *Device) Dial(ctx context.Context, a ble.Addr) (ble.Client, error) {
d.sendCmd(d.cm, 31, xpc.Dict{
d.sendCmd(d.cm, xpcID[cmdConnect], xpc.Dict{
"kCBMsgArgDeviceUUID": xpc.MakeUUID(a.String()),
"kCBMsgArgOptions": xpc.Dict{
"kCBConnectOptionNotifyOnDisconnection": 1,
......@@ -385,30 +367,29 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
switch m.id() {
case // Device event
evtStateChanged,
evtStateChangedPreHighSierra,
evtAdvertisingStarted,
evtAdvertisingStopped,
evtServiceAdded:
xpcID[evtStateChanged],
xpcID[evtAdvertisingStarted],
xpcID[evtAdvertisingStopped],
xpcID[evtServiceAdded]:
d.rspc <- args
case evtPeripheralDiscovered:
case xpcID[evtPeripheralDiscovered]:
if d.advHandler == nil {
break
}
a := &adv{args: m.args(), ad: args.advertisementData()}
go d.advHandler(a)
case evtConfirmation:
case xpcID[evtConfirmation]:
// log.Printf("confirmed: %d", args.attributeID())
case evtATTMTU:
case xpcID[evtATTMTU]:
d.conn(args).SetTxMTU(args.attMTU())
case evtSleveConnectionComplete:
case xpcID[evtSlaveConnectionComplete]:
// remote peripheral is connected.
fallthrough
case evtMasterConnectionComplete:
case xpcID[evtMasterConnectionComplete]:
// remote central is connected.
// Could be LEConnectionComplete or LEConnectionUpdateComplete.
......@@ -417,7 +398,7 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
c.connLatency = args.connectionLatency()
c.supervisionTimeout = args.supervisionTimeout()
case evtReadRequest:
case xpcID[evtReadRequest]:
aid := args.attributeID()
char := d.chars[aid]
v := char.Value
......@@ -430,14 +411,14 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
v = buf.Bytes()
}
d.sendCmd(d.pm, 13, xpc.Dict{
d.sendCmd(d.pm, xpcID[cmdSendData], xpc.Dict{
"kCBMsgArgAttributeID": aid,
"kCBMsgArgData": v,
"kCBMsgArgTransactionID": args.transactionID(),
"kCBMsgArgResult": 0,
})
case evtWriteRequest:
case xpcID[evtWriteRequest]:
for _, xxw := range args.attWrites() {
xw := msg(xxw.(xpc.Dict))
aid := xw.attributeID()
......@@ -447,7 +428,7 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
if xw.ignoreResponse() == 1 {
continue
}
d.sendCmd(d.pm, 13, xpc.Dict{
d.sendCmd(d.pm, xpcID[cmdSendData], xpc.Dict{
"kCBMsgArgAttributeID": aid,
"kCBMsgArgData": nil,
"kCBMsgArgTransactionID": args.transactionID(),
......@@ -455,18 +436,18 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
})
}
case evtSubscribe:
case xpcID[evtSubscribe]:
// characteristic is subscribed by remote central.
d.conn(args).subscribed(d.chars[args.attributeID()])
case evtUnubscribe:
case xpcID[evtUnsubscribe]:
// characteristic is unsubscribed by remote central.
d.conn(args).unsubscribed(d.chars[args.attributeID()])
case evtPeripheralConnected:
case xpcID[evtPeripheralConnected]:
d.chConn <- d.conn(args)
case evtPeripheralDisconnected:
case xpcID[evtPeripheralDisconnected]:
c := d.conn(args)
select {
case c.rspc <- m:
......@@ -479,7 +460,7 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
d.connLock.Unlock()
close(c.done)
case evtCharacteristicRead:
case xpcID[evtCharacteristicRead]:
// Notification
c := d.conn(args)
if args.isNotification() != 0 {
......@@ -495,15 +476,15 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
c.rspc <- m
case // Peripheral events
evtRSSIRead,
evtServiceDiscovered,
evtIncludedServicesDiscovered,
evtCharacteristicsDiscovered,
evtCharacteristicWritten,
evtNotificationValueSet,
evtDescriptorsDiscovered,
evtDescriptorRead,
evtDescriptorWritten:
xpcID[evtRSSIRead],
xpcID[evtServiceDiscovered],
xpcID[evtIncludedServicesDiscovered],
xpcID[evtCharacteristicsDiscovered],
xpcID[evtCharacteristicWritten],
xpcID[evtNotificationValueSet],
xpcID[evtDescriptorsDiscovered],
xpcID[evtDescriptorRead],
xpcID[evtDescriptorWritten]:
d.conn(args).rspc <- m
......
package darwin
import (
"github.com/raff/goble/xpc"
)
// xpc command IDs are OS X version specific, so we will use a map
// to be able to handle arbitrary versions
const (
cmdInit = iota
cmdAdvertiseStart
cmdAdvertiseStop
cmdScanningStart
cmdScanningStop
cmdServicesAdd
cmdServicesRemove
cmdSendData
cmdSubscribed
cmdConnect
cmdDisconnect
cmdReadRSSI
cmdDiscoverServices
cmdDiscoverIncludedServices
cmdDiscoverCharacteristics
cmdReadCharacteristic
cmdWriteCharacteristic
cmdSubscribeCharacteristic
cmdDiscoverDescriptors
cmdReadDescriptor
cmdWriteDescriptor
evtStateChanged
evtAdvertisingStarted
evtAdvertisingStopped
evtServiceAdded
evtReadRequest
evtWriteRequest
evtSubscribe
evtUnsubscribe
evtConfirmation
evtPeripheralDiscovered
evtPeripheralConnected
evtPeripheralDisconnected
evtATTMTU
evtRSSIRead
evtServiceDiscovered
evtIncludedServicesDiscovered
evtCharacteristicsDiscovered
evtCharacteristicRead
evtCharacteristicWritten
evtNotificationValueSet
evtDescriptorsDiscovered
evtDescriptorRead
evtDescriptorWritten
evtSlaveConnectionComplete
evtMasterConnectionComplete
)
// XpcIDs is the map of the commands for the current version of OS X
var xpcID map[int]int
func initXpcIDs() {
var utsname xpc.Utsname
xpc.Uname(&utsname)
xpcID = make(map[int]int)
xpcID[cmdInit] = 1
xpcID[cmdAdvertiseStart] = 8
xpcID[cmdAdvertiseStop] = 9
xpcID[cmdServicesAdd] = 10
xpcID[cmdServicesRemove] = 12
if utsname.Release < "17." {
// yosemite
xpcID[cmdSendData] = 13
xpcID[cmdSubscribed] = 15
xpcID[cmdScanningStart] = 29
xpcID[cmdScanningStop] = 30
xpcID[cmdConnect] = 31
xpcID[cmdDisconnect] = 32
xpcID[cmdReadRSSI] = 44
xpcID[cmdDiscoverServices] = 45
xpcID[cmdDiscoverIncludedServices] = 60
xpcID[cmdDiscoverCharacteristics] = 62
xpcID[cmdReadCharacteristic] = 65
xpcID[cmdWriteCharacteristic] = 66
xpcID[cmdSubscribeCharacteristic] = 68
xpcID[cmdDiscoverDescriptors] = 70
xpcID[cmdReadDescriptor] = 77
xpcID[cmdWriteDescriptor] = 78
xpcID[evtStateChanged] = 6
xpcID[evtAdvertisingStarted] = 16
xpcID[evtAdvertisingStopped] = 17
xpcID[evtServiceAdded] = 18
xpcID[evtReadRequest] = 19
xpcID[evtWriteRequest] = 20
xpcID[evtSubscribe] = 21
xpcID[evtUnsubscribe] = 22
xpcID[evtConfirmation] = 23
xpcID[evtPeripheralDiscovered] = 37
xpcID[evtPeripheralConnected] = 38
xpcID[evtPeripheralDisconnected] = 40
xpcID[evtATTMTU] = 53
xpcID[evtRSSIRead] = 55
xpcID[evtServiceDiscovered] = 56
xpcID[evtIncludedServicesDiscovered] = 63
xpcID[evtCharacteristicsDiscovered] = 64
xpcID[evtCharacteristicRead] = 71
xpcID[evtCharacteristicWritten] = 72
xpcID[evtNotificationValueSet] = 74
xpcID[evtDescriptorsDiscovered] = 76
xpcID[evtDescriptorRead] = 79
xpcID[evtDescriptorWritten] = 80
xpcID[evtSlaveConnectionComplete] = 81
xpcID[evtMasterConnectionComplete] = 82
} else {
// high sierra
xpcID[cmdSendData] = 13 // TODO: find out the correct value for this
xpcID[cmdScanningStart] = 44
xpcID[cmdScanningStop] = 45
xpcID[cmdConnect] = 46
xpcID[cmdDisconnect] = 47
xpcID[cmdReadRSSI] = 61
xpcID[cmdDiscoverServices] = 62
xpcID[cmdDiscoverIncludedServices] = 74
xpcID[cmdDiscoverCharacteristics] = 75
xpcID[cmdReadCharacteristic] = 78
xpcID[cmdWriteCharacteristic] = 79
xpcID[cmdSubscribeCharacteristic] = 81
xpcID[cmdDiscoverDescriptors] = 82
xpcID[cmdReadDescriptor] = 88
xpcID[cmdWriteDescriptor] = 89
xpcID[evtStateChanged] = 4
xpcID[evtPeripheralDiscovered] = 48
xpcID[evtPeripheralConnected] = 49
xpcID[evtPeripheralDisconnected] = 50
xpcID[evtRSSIRead] = 71
xpcID[evtServiceDiscovered] = 72
xpcID[evtCharacteristicsDiscovered] = 77
xpcID[evtCharacteristicRead] = 83
xpcID[evtCharacteristicWritten] = 84
xpcID[evtNotificationValueSet] = 86
xpcID[evtDescriptorsDiscovered] = 87
xpcID[evtDescriptorRead] = 90
xpcID[evtDescriptorWritten] = 91
// TODO: find out the correct values for the following items.
// They have all just been copied from Yosemite values
xpcID[evtAdvertisingStarted] = 16
xpcID[evtAdvertisingStopped] = 17
xpcID[evtServiceAdded] = 18
xpcID[evtReadRequest] = 19
xpcID[evtWriteRequest] = 20
xpcID[evtSubscribe] = 21
xpcID[evtUnsubscribe] = 22
xpcID[evtConfirmation] = 23
xpcID[evtATTMTU] = 53
xpcID[evtSlaveConnectionComplete] = 81
xpcID[evtMasterConnectionComplete] = 82
xpcID[evtIncludedServicesDiscovered] = 87
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment