bt_dbus: bypass nim-dbus getPrimitive bug with robust custom parser
This commit is contained in:
parent
d250f8b6ab
commit
7e3c8c8e47
2 changed files with 105 additions and 8 deletions
6
PKGBUILD
6
PKGBUILD
|
|
@ -41,12 +41,14 @@ build() {
|
||||||
patch_dbus
|
patch_dbus
|
||||||
rm -rf "$srcdir/nimcache"
|
rm -rf "$srcdir/nimcache"
|
||||||
nim c \
|
nim c \
|
||||||
--path:"$NIMBLE_DIR/pkgs2" \
|
--noNimblePath \
|
||||||
|
--nimblePath:"$NIMBLE_DIR/pkgs2" \
|
||||||
--nimcache:"$srcdir/nimcache" \
|
--nimcache:"$srcdir/nimcache" \
|
||||||
--mm:orc -d:release --opt:speed --hints:off \
|
--mm:orc -d:release --opt:speed --hints:off \
|
||||||
-o:build/nbt src/nbt.nim
|
-o:build/nbt src/nbt.nim
|
||||||
nim c \
|
nim c \
|
||||||
--path:"$NIMBLE_DIR/pkgs2" \
|
--noNimblePath \
|
||||||
|
--nimblePath:"$NIMBLE_DIR/pkgs2" \
|
||||||
--nimcache:"$srcdir/nimcache" \
|
--nimcache:"$srcdir/nimcache" \
|
||||||
--mm:orc -d:release --opt:speed --hints:off \
|
--mm:orc -d:release --opt:speed --hints:off \
|
||||||
-o:build/nimbt-daemon src/nimbt_daemon.nim
|
-o:build/nimbt-daemon src/nimbt_daemon.nim
|
||||||
|
|
|
||||||
107
src/bt_dbus.nim
107
src/bt_dbus.nim
|
|
@ -22,6 +22,8 @@ proc newBluezConn*(): BluezConn =
|
||||||
result.adapters = @[]
|
result.adapters = @[]
|
||||||
result.devices = @[]
|
result.devices = @[]
|
||||||
|
|
||||||
|
proc readDbusValueRaw*(iter: ptr DBusMessageIter): DbusValue
|
||||||
|
|
||||||
proc dbusCall*(bz: BluezConn; path, iface, methodName: string; args: openarray[DbusValue] = []): Reply =
|
proc dbusCall*(bz: BluezConn; path, iface, methodName: string; args: openarray[DbusValue] = []): Reply =
|
||||||
var msg = makeCall(BluezDest, path.ObjectPath, iface, methodName)
|
var msg = makeCall(BluezDest, path.ObjectPath, iface, methodName)
|
||||||
for a in args:
|
for a in args:
|
||||||
|
|
@ -32,8 +34,8 @@ proc dbusCall*(bz: BluezConn; path, iface, methodName: string; args: openarray[D
|
||||||
|
|
||||||
proc dbusGet*(bz: BluezConn; path, iface, prop: string): DbusValue =
|
proc dbusGet*(bz: BluezConn; path, iface, prop: string): DbusValue =
|
||||||
let reply = bz.dbusCall(path, PropIface, "Get", @[iface.asDbusValue, prop.asDbusValue])
|
let reply = bz.dbusCall(path, PropIface, "Get", @[iface.asDbusValue, prop.asDbusValue])
|
||||||
var iter = reply.iterate()
|
var inputIter = reply.iterate()
|
||||||
var val = iter.unpackCurrent(DbusValue)
|
var val = readDbusValueRaw(cast[ptr DBusMessageIter](addr inputIter))
|
||||||
if val != nil and val.kind == dtVariant:
|
if val != nil and val.kind == dtVariant:
|
||||||
val = val.variantValue
|
val = val.variantValue
|
||||||
result = val
|
result = val
|
||||||
|
|
@ -47,8 +49,8 @@ proc dbusCallMethod*(bz: BluezConn; path, iface, methodName: string; args: opena
|
||||||
|
|
||||||
proc dbusGetAll*(bz: BluezConn; path, iface: string): Table[string, DbusValue] =
|
proc dbusGetAll*(bz: BluezConn; path, iface: string): Table[string, DbusValue] =
|
||||||
let reply = bz.dbusCall(path, PropIface, "GetAll", @[iface.asDbusValue])
|
let reply = bz.dbusCall(path, PropIface, "GetAll", @[iface.asDbusValue])
|
||||||
var iter = reply.iterate()
|
var inputIter = reply.iterate()
|
||||||
let val = iter.unpackCurrent(DbusValue)
|
let val = readDbusValueRaw(cast[ptr DBusMessageIter](addr inputIter))
|
||||||
if val.kind == dtArray:
|
if val.kind == dtArray:
|
||||||
for entry in val.arrayValue:
|
for entry in val.arrayValue:
|
||||||
if entry.kind == dtDictEntry:
|
if entry.kind == dtDictEntry:
|
||||||
|
|
@ -107,10 +109,103 @@ proc propsToAdapter(path: string; props: Table[string, DbusValue]): Adapter =
|
||||||
result.discoverable = props.getOrDefault("Discoverable", DbusValue(kind: dtBool, boolValue: false)).boolValue
|
result.discoverable = props.getOrDefault("Discoverable", DbusValue(kind: dtBool, boolValue: false)).boolValue
|
||||||
result.pairable = props.getOrDefault("Pairable", DbusValue(kind: dtBool, boolValue: false)).boolValue
|
result.pairable = props.getOrDefault("Pairable", DbusValue(kind: dtBool, boolValue: false)).boolValue
|
||||||
|
|
||||||
|
proc readDbusValueRaw(iter: ptr DBusMessageIter): DbusValue =
|
||||||
|
let kind = cast[DbusTypeChar](dbus_message_iter_get_arg_type(iter))
|
||||||
|
case kind:
|
||||||
|
of dtNull:
|
||||||
|
return DbusValue(kind: dtNull)
|
||||||
|
of dtBool:
|
||||||
|
var v: dbus_uint32_t
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtBool, boolValue: v != 0)
|
||||||
|
of dtDouble:
|
||||||
|
var v: float64
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtDouble, doubleValue: v)
|
||||||
|
of dtInt32:
|
||||||
|
var v: int32
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtInt32, int32Value: v)
|
||||||
|
of dtInt16:
|
||||||
|
var v: int16
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtInt16, int16Value: v)
|
||||||
|
of dtUint16:
|
||||||
|
var v: uint16
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtUint16, uint16Value: v)
|
||||||
|
of dtUint64:
|
||||||
|
var v: uint64
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtUint64, uint64Value: v)
|
||||||
|
of dtUint32:
|
||||||
|
var v: dbus_uint32_t
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtUint32, uint32Value: v)
|
||||||
|
of dtInt64:
|
||||||
|
var v: int64
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtInt64, int64Value: v)
|
||||||
|
of dtByte:
|
||||||
|
var v: uint8
|
||||||
|
dbus_message_iter_get_basic(iter, addr v)
|
||||||
|
return DbusValue(kind: dtByte, byteValue: v)
|
||||||
|
of dtString:
|
||||||
|
var s: cstring
|
||||||
|
dbus_message_iter_get_basic(iter, addr s)
|
||||||
|
return DbusValue(kind: dtString, stringValue: $s)
|
||||||
|
of dtObjectPath:
|
||||||
|
var s: cstring
|
||||||
|
dbus_message_iter_get_basic(iter, addr s)
|
||||||
|
return DbusValue(kind: dtObjectPath, objectPathValue: ($s).ObjectPath)
|
||||||
|
of dtSignature:
|
||||||
|
var s: cstring
|
||||||
|
dbus_message_iter_get_basic(iter, addr s)
|
||||||
|
return DbusValue(kind: dtSignature, signatureValue: ($s).Signature)
|
||||||
|
of dtVariant:
|
||||||
|
var subiter: DBusMessageIter
|
||||||
|
dbus_message_iter_recurse(iter, addr subiter)
|
||||||
|
let subvalue = readDbusValueRaw(addr subiter)
|
||||||
|
return DbusValue(kind: dtVariant, variantType: subvalue.kind, variantValue: subvalue)
|
||||||
|
of dtDictEntry:
|
||||||
|
var subiter: DBusMessageIter
|
||||||
|
dbus_message_iter_recurse(iter, addr subiter)
|
||||||
|
let key = readDbusValueRaw(addr subiter)
|
||||||
|
discard dbus_message_iter_next(addr subiter)
|
||||||
|
let val = readDbusValueRaw(addr subiter)
|
||||||
|
return DbusValue(kind: dtDictEntry, dictKey: key, dictValue: val)
|
||||||
|
of dtArray:
|
||||||
|
var subiter: DBusMessageIter
|
||||||
|
dbus_message_iter_recurse(iter, addr subiter)
|
||||||
|
var values: seq[DbusValue]
|
||||||
|
var subkind: DbusType
|
||||||
|
while true:
|
||||||
|
let subkindInt = dbus_message_iter_get_arg_type(addr subiter)
|
||||||
|
subkind = cast[DbusTypeChar](subkindInt)
|
||||||
|
if subkind.kind == dtNull: break
|
||||||
|
values.add(readDbusValueRaw(addr subiter))
|
||||||
|
if dbus_message_iter_has_next(addr subiter) == 0: break
|
||||||
|
discard dbus_message_iter_next(addr subiter)
|
||||||
|
if values.len > 0 and subkind.kind == dtDictEntry:
|
||||||
|
subkind.keyType = values[0].dictKey.kind
|
||||||
|
subkind.valueType = values[0].dictValue.kind
|
||||||
|
return DbusValue(kind: dtArray, arrayValueType: subkind, arrayValue: values)
|
||||||
|
of dtStruct:
|
||||||
|
var subiter: DBusMessageIter
|
||||||
|
dbus_message_iter_recurse(iter, addr subiter)
|
||||||
|
var values: seq[DbusValue]
|
||||||
|
while true:
|
||||||
|
values.add(readDbusValueRaw(addr subiter))
|
||||||
|
if dbus_message_iter_has_next(addr subiter) == 0: break
|
||||||
|
discard dbus_message_iter_next(addr subiter)
|
||||||
|
return DbusValue(kind: dtStruct, structValues: values)
|
||||||
|
else:
|
||||||
|
raise newException(DbusException, "nim-bt does not support D-Bus type " & $kind)
|
||||||
|
|
||||||
proc refresh*(bz: BluezConn) =
|
proc refresh*(bz: BluezConn) =
|
||||||
let reply = bz.dbusCall(BluezPath, ObjMgrIface, "GetManagedObjects")
|
let reply = bz.dbusCall(BluezPath, ObjMgrIface, "GetManagedObjects")
|
||||||
var iter = reply.iterate()
|
var inputIter = reply.iterate()
|
||||||
let root = iter.unpackCurrent(DbusValue)
|
let root = readDbusValueRaw(cast[ptr DBusMessageIter](addr inputIter))
|
||||||
bz.adapters = @[]
|
bz.adapters = @[]
|
||||||
bz.devices = @[]
|
bz.devices = @[]
|
||||||
if root.kind == dtArray:
|
if root.kind == dtArray:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue