Control4Savant Posted January 7, 2022 Share Posted January 7, 2022 22 hours ago, IntrinsicGroup said: - the resources needed for this driver simply don't existing at all in the Control4 (or other control platform) sandboxes. This has meant we have to build processes from scratch - I am not sure I understand this …Are you referring to mini apps? Quote Link to comment Share on other sites More sharing options...
IntrinsicGroup Posted January 7, 2022 Share Posted January 7, 2022 16 minutes ago, Control4Savant said: I am not sure I understand this …Are you referring to mini apps? No the actual API in which drivers are created with Control4 - it’s based on a Sandboxed (restricted) version of LUA and the raw function calls and libraries needed to leverage the systems employed by Apple just didn’t exist, so we’ve had to build them from scratch and find a way to get them to run within this framework. Quote Link to comment Share on other sites More sharing options...
South Africa C4 user Posted January 7, 2022 Share Posted January 7, 2022 23 minutes ago, IntrinsicGroup said: No the actual API in which drivers are created with Control4 - it’s based on a Sandboxed (restricted) version of LUA and the raw function calls and libraries needed to leverage the systems employed by Apple just didn’t exist, so we’ve had to build them from scratch and find a way to get them to run within this framework. I must say, I am still confused given you has TVOS14 working…. But I am not a techie! Quote Link to comment Share on other sites More sharing options...
Rexabyte Posted January 7, 2022 Share Posted January 7, 2022 I haven't touched the API in question but I can hopefully explain the time things can take and libraries. A while ago I wanted to create an Xbox driver that works over the SmartGlass protocol. While this would be relatively easy if you had the SDK that Microsoft provides it is much more difficult in a sandboxed environment (Control4) where you cannot use the SDK provided by Microsoft. Instead you need to work with the raw protocol (bits and bytes) and write all of the logic required just to even communicate to the Xbox. Sometimes you can find opensource MIT licensed code to do portions of what you need, other times you need to write it yourself. So what would it take to write everything required where the libraries don't exist in Control4? Let's start with JUST the crypto portion: https://openxbox.org/smartglass-documentation/cryptography/#key-exchange On Discovery, the console responds with a Discovery Response including a certificate, this certificate holds the console's public key. The client generates elliptic curve and derives the shared secret with console's public key using ECDH and a randomly generated public/private keypair The shared secret is salted using static salts, see KDF Salts The salted shared secret is hashed using SHA-512 The salted & hashed shared secret is split into the following individual keys: bytes 0-16: Encryption key (AES-128-CBC) bytes 16-32: Initialization Vector key (AES-128-CBC) bytes 32-64: Hashing key (HMAC-SHA-256) The client's public key is sent inside the Connect Request message to the console First things first we need to get the public key from the certificate. So we need to parse out the response and format it. It's received in an ASN. The following code (incomplete, needs to support more types, also using a custom library, BitHelper, to read bits and bytes) is used just to parse the ASN to get the public key used in step 2. After that we still need to do encryption using ECDH, which if not supported in Control4's encryption methods also needs to be written or sourced from somewhere. This can go on and on. ASN = (function() local class = {}; class.__index = class local Types = { BOOLEAN = 0x01, INTEGER = 0x02, STRING = 0x03, OCTET = 0x04, NULL = 0x05, OBJECT = 0x06, UTF8String = 0x0C, IA5STRING= 0x16, SEQUENCE = 0x30, SET = 0x31, } class.Map = { [0x01] = "DecodeBoolean", [0x02] = "DecodeInteger", [0x03] = "DecodeString", [0x04] = "DecodeOctet", [0x05] = "DecodeNull", [0x06] = "DecodeObject", [0x0C] = "DecodeUTF8String", [0x13] = "DecodeUTF8String", [0x16] = "DecodeIA5String", [0x17] = "DecodeUTCTime", [0x30] = "DecodeSequence", [0x31] = "DecodeSet", } class.Class = { ["Universal"] = 0, ["Application"] = 1, ["Context"] = 2, ["Private" ] = 3 } function class.DecodeSet(data, pos) Logger.Trace("ASN.DecodeSet: " .. pos) pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) local p, obj = class.Parse(d) return pos, obj end function class.DecodeOctet(data, pos) local l,d pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) return pos, d end function class.DecodeUTCTime(data, pos) Logger.Trace("ASN.DecodeUTCTime") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeString(data, pos) Logger.Trace("ASN.DecodeString") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeUTF8String(data, pos) Logger.Trace("ASN.DecodeUTF8String") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeLength(data, pos) Logger.Trace("ASN.DecodeLength") local length = nil pos, length = BitHelper.GetInt8(data, pos) local isLong = bit.band(length, 0x80) ~= 0 --print("LONG: " .. tostring(isLong)) if (isLong) then local bytes = bit.band(length, 0x7F) Logger.Debug("BYTES: " .. bytes) Logger.Debug(hexdump(string.sub(data, pos, pos + bytes - 1))) if (bytes == 1) then pos, length = BitHelper.GetInt8(data, pos) elseif (bytes == 2) then pos, length = BitHelper.GetInt16(data, pos) elseif (bytes == 4) then pos, length = BitHelper.GetInt32(data, pos) else Logger.Error("BAD LENGTH") end --print("LENGTH: " .. length) else Logger.Debug("LENGTH: " .. length) Logger.Debug(hexdump(string.sub(data, pos - 1, pos))) end return pos, length end function class.DecodeSequence(data, pos) Logger.Trace("ASN.DecodeSequence: " .. pos) --print(hexdump(string.sub(data, pos))) pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) local p, obj = class.Parse(d) return pos, obj end function class.DecodeSequenceOf() end function class.DecodeInteger(data, pos) Logger.Trace("ASN.DecodeInteger") local start = pos pos, length = class.DecodeLength(data, pos) if (length == 1) then return BitHelper.GetInt8(data, pos) elseif (length == 2) then return BitHelper.GetInt16(data, pos) elseif (length == 4) then return BitHelper.GetInt32(data, pos) else return BitHelper.GetString(data, pos, length) end end function class.DecodeContext(data, pos) Logger.Trace("ASN.DecodeContext") local length, d pos, length = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, length) local _, obj = class.Parse(d) return pos, obj end function class.DecodeObject(data, pos) Logger.Trace("ASN.DecodeObject") local length = 0 pos, length = class.DecodeLength(data, pos) local d = string.sub(data, pos, pos + length) local p, firstByte = BitHelper.GetInt8(d) local firstDigit = firstByte / 40; local secondDigit = firstByte % 40; local nodes = { firstDigit, secondDigit } -- TODO: Determine OID value return pos + length, d end function class.DecodeNull(data, pos) pos, length = class.DecodeLength(data, pos) return pos, false end function class.DecodeBoolean(data, pos) Logger.Trace("ASN.DecodeBoolean") pos, length = class.DecodeLength(data, pos) pos, d = BitHelper.GetInt8(data, pos) return pos, d end function class.DecodeChoice() end function class.Parse(certificate, pos) Logger.Trace("ASN.Parse") local pos = pos or 1 local limit = 1 local obj = {} while (pos < #certificate) do local t, l, d pos, t = BitHelper.GetInt8(certificate, pos) local f = bit.rshift(bit.band(t, 0x20), 5) local c = bit.rshift(bit.band(t, 0xC0), 6) local method = class.Map[t] if (method and class[method]) then Logger.Trace(method) pos, d = class[method](certificate, pos) obj[#obj + 1] = d else if (c == class.Class.Context) then pos, d = class.DecodeContext(certificate, pos) else Logger.Error("BAD METHOD: " .. t) end end end return pos, obj end local mt = { __call = function(self) local instance = {} setmetatable(instance, class) return instance end, } setmetatable(class, mt) return class end) () Quote Link to comment Share on other sites More sharing options...
BuffaloC4 Posted January 7, 2022 Share Posted January 7, 2022 23 minutes ago, Rexabyte said: I haven't touched the API in question but I can hopefully explain the time things can take and libraries. A while ago I wanted to create an Xbox driver that works over the SmartGlass protocol. While this would be relatively easy if you had the SDK that Microsoft provides it is much more difficult in a sandboxed environment (Control4) where you cannot use the SDK provided by Microsoft. Instead you need to work with the raw protocol (bits and bytes) and write all of the logic required just to even communicate to the Xbox. Sometimes you can find opensource MIT licensed code to do portions of what you need, other times you need to write it yourself. So what would it take to write everything required where the libraries don't exist in Control4? Let's start with JUST the crypto portion: https://openxbox.org/smartglass-documentation/cryptography/#key-exchange On Discovery, the console responds with a Discovery Response including a certificate, this certificate holds the console's public key. The client generates elliptic curve and derives the shared secret with console's public key using ECDH and a randomly generated public/private keypair The shared secret is salted using static salts, see KDF Salts The salted shared secret is hashed using SHA-512 The salted & hashed shared secret is split into the following individual keys: bytes 0-16: Encryption key (AES-128-CBC) bytes 16-32: Initialization Vector key (AES-128-CBC) bytes 32-64: Hashing key (HMAC-SHA-256) The client's public key is sent inside the Connect Request message to the console First things first we need to get the public key from the certificate. So we need to parse out the response and format it. It's received in an ASN. The following code (incomplete, needs to support more types, also using a custom library, BitHelper, to read bits and bytes) is used just to parse the ASN to get the public key used in step 2. After that we still need to do encryption using ECDH, which if not supported in Control4's encryption methods also needs to be written or sourced from somewhere. This can go on and on. ASN = (function() local class = {}; class.__index = class local Types = { BOOLEAN = 0x01, INTEGER = 0x02, STRING = 0x03, OCTET = 0x04, NULL = 0x05, OBJECT = 0x06, UTF8String = 0x0C, IA5STRING= 0x16, SEQUENCE = 0x30, SET = 0x31, } class.Map = { [0x01] = "DecodeBoolean", [0x02] = "DecodeInteger", [0x03] = "DecodeString", [0x04] = "DecodeOctet", [0x05] = "DecodeNull", [0x06] = "DecodeObject", [0x0C] = "DecodeUTF8String", [0x13] = "DecodeUTF8String", [0x16] = "DecodeIA5String", [0x17] = "DecodeUTCTime", [0x30] = "DecodeSequence", [0x31] = "DecodeSet", } class.Class = { ["Universal"] = 0, ["Application"] = 1, ["Context"] = 2, ["Private" ] = 3 } function class.DecodeSet(data, pos) Logger.Trace("ASN.DecodeSet: " .. pos) pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) local p, obj = class.Parse(d) return pos, obj end function class.DecodeOctet(data, pos) local l,d pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) return pos, d end function class.DecodeUTCTime(data, pos) Logger.Trace("ASN.DecodeUTCTime") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeString(data, pos) Logger.Trace("ASN.DecodeString") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeUTF8String(data, pos) Logger.Trace("ASN.DecodeUTF8String") pos, length = class.DecodeLength(data, pos) --print("STRING LENGTH: " .. length) pos, str = BitHelper.GetString(data, pos, length) --print("STRING: " .. str) return pos, str end function class.DecodeLength(data, pos) Logger.Trace("ASN.DecodeLength") local length = nil pos, length = BitHelper.GetInt8(data, pos) local isLong = bit.band(length, 0x80) ~= 0 --print("LONG: " .. tostring(isLong)) if (isLong) then local bytes = bit.band(length, 0x7F) Logger.Debug("BYTES: " .. bytes) Logger.Debug(hexdump(string.sub(data, pos, pos + bytes - 1))) if (bytes == 1) then pos, length = BitHelper.GetInt8(data, pos) elseif (bytes == 2) then pos, length = BitHelper.GetInt16(data, pos) elseif (bytes == 4) then pos, length = BitHelper.GetInt32(data, pos) else Logger.Error("BAD LENGTH") end --print("LENGTH: " .. length) else Logger.Debug("LENGTH: " .. length) Logger.Debug(hexdump(string.sub(data, pos - 1, pos))) end return pos, length end function class.DecodeSequence(data, pos) Logger.Trace("ASN.DecodeSequence: " .. pos) --print(hexdump(string.sub(data, pos))) pos, l = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, l) local p, obj = class.Parse(d) return pos, obj end function class.DecodeSequenceOf() end function class.DecodeInteger(data, pos) Logger.Trace("ASN.DecodeInteger") local start = pos pos, length = class.DecodeLength(data, pos) if (length == 1) then return BitHelper.GetInt8(data, pos) elseif (length == 2) then return BitHelper.GetInt16(data, pos) elseif (length == 4) then return BitHelper.GetInt32(data, pos) else return BitHelper.GetString(data, pos, length) end end function class.DecodeContext(data, pos) Logger.Trace("ASN.DecodeContext") local length, d pos, length = class.DecodeLength(data, pos) pos, d = BitHelper.GetString(data, pos, length) local _, obj = class.Parse(d) return pos, obj end function class.DecodeObject(data, pos) Logger.Trace("ASN.DecodeObject") local length = 0 pos, length = class.DecodeLength(data, pos) local d = string.sub(data, pos, pos + length) local p, firstByte = BitHelper.GetInt8(d) local firstDigit = firstByte / 40; local secondDigit = firstByte % 40; local nodes = { firstDigit, secondDigit } -- TODO: Determine OID value return pos + length, d end function class.DecodeNull(data, pos) pos, length = class.DecodeLength(data, pos) return pos, false end function class.DecodeBoolean(data, pos) Logger.Trace("ASN.DecodeBoolean") pos, length = class.DecodeLength(data, pos) pos, d = BitHelper.GetInt8(data, pos) return pos, d end function class.DecodeChoice() end function class.Parse(certificate, pos) Logger.Trace("ASN.Parse") local pos = pos or 1 local limit = 1 local obj = {} while (pos < #certificate) do local t, l, d pos, t = BitHelper.GetInt8(certificate, pos) local f = bit.rshift(bit.band(t, 0x20), 5) local c = bit.rshift(bit.band(t, 0xC0), 6) local method = class.Map[t] if (method and class[method]) then Logger.Trace(method) pos, d = class[method](certificate, pos) obj[#obj + 1] = d else if (c == class.Class.Context) then pos, d = class.DecodeContext(certificate, pos) else Logger.Error("BAD METHOD: " .. t) end end end return pos, obj end local mt = { __call = function(self) local instance = {} setmetatable(instance, class) return instance end, } setmetatable(class, mt) return class end) () Did you ever get this working? I bet people would employ you to do an Xbox driver for them. I know I would. Quote Link to comment Share on other sites More sharing options...
Rexabyte Posted January 7, 2022 Share Posted January 7, 2022 6 minutes ago, BuffaloC4 said: Did you ever get this working? I bet people would employ you to do an Xbox driver for them. I know I would. It was put on the back burner as we took on some non Control4 related projects. We never revisited it afterwards as the Series X released and it doesn't work over the same local communication method, it requires an internet connection and uses xCloud. Quote Link to comment Share on other sites More sharing options...
schaudhary77 Posted March 8, 2022 Share Posted March 8, 2022 So are we still waiting on the new driver? Last I read it was supposed to be released in January. Quote Link to comment Share on other sites More sharing options...
beingboard247 Posted March 10, 2022 Share Posted March 10, 2022 So is there any update? Is this still happening or is it just smoke and mirrors… Quote Link to comment Share on other sites More sharing options...
Amr Posted March 11, 2022 Share Posted March 11, 2022 On 3/10/2022 at 8:36 PM, beingboard247 said: So is there any update? Is this still happening or is it just smoke and mirrors… Use Jesse IR driver, u won’t need anything else, whatever Apple do with TvOS u will be immune to these changes … Quote Link to comment Share on other sites More sharing options...
beingboard247 Posted March 12, 2022 Share Posted March 12, 2022 4 hours ago, Amr said: Use Jesse IR driver, u won’t need anything else, whatever Apple do with TvOS u will be immune to these changes … I just gave it a go and I absolutely love it! I thought IP was the way to go but this driver is hands down better! Thanks for the tip sir! Quote Link to comment Share on other sites More sharing options...
IntrinsicGroup Posted March 13, 2022 Share Posted March 13, 2022 On 3/10/2022 at 7:36 PM, beingboard247 said: So is there any update? Is this still happening or is it just smoke and mirrors… We're still working on the new driver for tvOS 15 to supplement our tvOS 14 driver. We're sorry it's taking longer than planned but we're still actively working on it. We will update this forum as soon as we have more information and a release date. Glad you've found an alternative solution to get you sorted though Quote Link to comment Share on other sites More sharing options...
South Africa C4 user Posted March 13, 2022 Share Posted March 13, 2022 1 hour ago, IntrinsicGroup said: We're still working on the new driver for tvOS 15 to supplement our tvOS 14 driver. We're sorry it's taking longer than planned but we're still actively working on it. We will update this forum as soon as we have more information and a release date. Glad you've found an alternative solution to get you sorted though Will there be any improvements in the new driver (e.g. mini apps or meta data handling would make the wait worthwhile!). Quote Link to comment Share on other sites More sharing options...
IntrinsicGroup Posted March 17, 2022 Share Posted March 17, 2022 On 3/13/2022 at 8:31 PM, South Africa C4 user said: Will there be any improvements in the new driver (e.g. mini apps or meta data handling would make the wait worthwhile!). Hopefully - I can't make any promises on it though until the driver is completed but that's our intention. South Africa C4 user 1 Quote Link to comment Share on other sites More sharing options...
ekohn00 Posted March 17, 2022 Share Posted March 17, 2022 TVOS 16 beta in June, maybe skip ahead ?? BY96 and tmj4 1 1 Quote Link to comment Share on other sites More sharing options...
tmj4 Posted March 17, 2022 Share Posted March 17, 2022 26 minutes ago, ekohn00 said: TVOS 16 beta in June, maybe skip ahead ?? Was thinking the same. We're closer to tvOS 16 Beta than 15 GM at this point. Quote Link to comment Share on other sites More sharing options...
Amr Posted March 19, 2022 Share Posted March 19, 2022 On 3/17/2022 at 7:56 PM, tmj4 said: Was thinking the same. We're closer to tvOS 16 Beta than 15 GM at this point. 16 won’t change the control introduced in 15, although this is Apple and they can do whatever they think it’s an advantage Quote Link to comment Share on other sites More sharing options...
bk Posted June 3, 2022 Share Posted June 3, 2022 On 3/18/2022 at 4:10 AM, IntrinsicGroup said: Hopefully - I can't make any promises on it though until the driver is completed but that's our intention. Have you an update on this please, very frustrating that your product was recomended and i purchased last year only to have it to be forced redundant shortly afterward. Update expectations have been moved a number of times, I've been patiently waiting and using 2 remotes. Quote Link to comment Share on other sites More sharing options...
schaudhary77 Posted June 3, 2022 Share Posted June 3, 2022 8 hours ago, bk said: Have you an update on this please, very frustrating that your product was recomended and i purchased last year only to have it to be forced redundant shortly afterward. Update expectations have been moved a number of times, I've been patiently waiting and using 2 remotes. +1. This driver was supposed to be ready last October. All we've heard is it'll be ready soon, it'll be ready next month and so on, without any results. If you are not going to stand behind your product. go ahead and say so and be done with it. Quote Link to comment Share on other sites More sharing options...
msgreenf Posted June 3, 2022 Share Posted June 3, 2022 I highly doubt they were beta testing in the time window they said they were or else it would have been released jmb 1 Quote Link to comment Share on other sites More sharing options...
South Africa C4 user Posted June 3, 2022 Share Posted June 3, 2022 I must say that I still have no issues with the native driver (6 Apple TV’s across 2 houses) but I was hoping this driver would add something extra like mini Apps or meta data. C4 User 1 Quote Link to comment Share on other sites More sharing options...
Amr Posted June 3, 2022 Share Posted June 3, 2022 This is a project for sure, requires massive work, I prefer it they abandon it and say so, we moved on already. Quote Link to comment Share on other sites More sharing options...
Amr Posted June 3, 2022 Share Posted June 3, 2022 4 hours ago, South Africa C4 user said: I must say that I still have no issues with the native driver (6 Apple TV’s across 2 houses) but I was hoping this driver would add something extra like mini Apps or meta data. https://github.com/13mralex/c4-pyatv-remote This driver will provide you with MiniApps on Apple TV! jimbones, Andrew H and South Africa C4 user 2 1 Quote Link to comment Share on other sites More sharing options...
jmb Posted June 7, 2022 Share Posted June 7, 2022 On 6/3/2022 at 12:49 PM, schaudhary77 said: +1. This driver was supposed to be ready last October. All we've heard is it'll be ready soon, it'll be ready next month and so on, without any results. If you are not going to stand behind your product. go ahead and say so and be done with it. It would be reasonable for @IntrinsicGroup to provide some update at this point, bad news would be better than no news. If you have dropped the product be upfront about it. Apple has now announced the next version of tvOS 16. Quote Link to comment Share on other sites More sharing options...
Neo1738 Posted June 7, 2022 Share Posted June 7, 2022 14 minutes ago, jmb said: It would be reasonable for @IntrinsicGroup to provide some update at this point, bad news would be better than no news. If you have dropped the product be upfront about it. Apple has now announced the next version of tvOS 16. I have fears intrinsic isn't doing any updates. They've also been working on Tesla driver for at least 6 mo. jmb 1 Quote Link to comment Share on other sites More sharing options...
Amr Posted June 7, 2022 Share Posted June 7, 2022 Guys move on there are good alternatives out there, myself am going to move to C4 original AppleTV driver once I move to EA5, planned before Christmas this year . Unofficial drivers using unpublished API’s will always breaks at one point! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.