Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(macos): reading descriptor value #391

Merged
merged 3 commits into from
Jul 23, 2024

Conversation

kovapatrik
Copy link
Contributor

@kovapatrik kovapatrik commented Jul 15, 2024

Reading out the value of the descriptors was not correctly implemented before. My solution needs to be extended with all the possible standards descriptor UUIDs but it provides a good starting point.

Also fixes a delegate bug (there were incorrect methods assigned to the functions)

trace!("Getting data!");
let v = unsafe { descriptor.value() }.map(|value| unsafe {
match descriptor.UUID().UUIDString().to_string().as_str() {
"2901" => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's special about "2901" here? Why can't this work for other descriptor UUIDs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are predefined UUIDs for descriptors for which we know the type for (in case of 2901, it is NSString). I think it's possible to create custom descriptors, but without knowing what the underlying type if for that it's not possible to get the value (AFAIK)

The predefined descriptor UUIDs are in this pdf, in section 3.7:

https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Assigned_Numbers/out/en/Assigned_Numbers.pdf?v=1720988510534

Copy link
Contributor Author

@kovapatrik kovapatrik Jul 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention the root problem: descriptor.value() is a Retained<AnyObject>. It must be cast to a type and it will throw an error if you try to cast it to an invalid type. So in this case if I would try to cast the value to for example NSData instead of NSString, it will throw an error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see in the Apple documentation, it looks like the value will either be an NSString, NSData, NSNumber or UInt16. Can you use AnyObject::class to check which type it is, then cast and convert it accordingly? This should be more robust and general than special-casing each UUID.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to trace back to the superclass of the class because in my case I have the same descriptor within 5 different characteristic and in one characteristic the type was NSTaggedPointerString, in the other one it was __NSCFString. Both are subclasses of NSString and can be safely cast to it. This way it's a bit hacky to get the value of NSNumber. Do you have any suggestions how should I get the class of a number this way? Also, should we panic if there are no matching class type?

@kovapatrik kovapatrik requested a review from qwandor July 17, 2024 20:08
@qwandor qwandor merged commit c9583b1 into deviceplug:dev Jul 23, 2024
4 checks passed
@kovapatrik kovapatrik deleted the fix/read-descriptor branch July 23, 2024 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants