| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device_class.h" |
| |
| #include <zircon/assert.h> |
| |
| namespace bt { |
| |
| namespace { |
| |
| DeviceClass::ServiceClass bit_no_to_service_class(uint8_t bit_no) { |
| ZX_DEBUG_ASSERT(bit_no >= 16); |
| ZX_DEBUG_ASSERT(bit_no < 24); |
| switch (bit_no) { |
| case 16: |
| return DeviceClass::ServiceClass::kPositioning; |
| case 17: |
| return DeviceClass::ServiceClass::kNetworking; |
| case 18: |
| return DeviceClass::ServiceClass::kRendering; |
| case 19: |
| return DeviceClass::ServiceClass::kCapturing; |
| case 20: |
| return DeviceClass::ServiceClass::kObjectTransfer; |
| case 21: |
| return DeviceClass::ServiceClass::kAudio; |
| case 22: |
| return DeviceClass::ServiceClass::kTelephony; |
| case 23: |
| return DeviceClass::ServiceClass::kInformation; |
| }; |
| // Should be unreachable. |
| return DeviceClass::ServiceClass::kInformation; |
| } |
| |
| std::string service_class_to_string(const DeviceClass::ServiceClass& serv) { |
| switch (serv) { |
| case DeviceClass::ServiceClass::kPositioning: |
| return "Positioning"; |
| case DeviceClass::ServiceClass::kNetworking: |
| return "Networking"; |
| case DeviceClass::ServiceClass::kRendering: |
| return "Rendering"; |
| case DeviceClass::ServiceClass::kCapturing: |
| return "Capturing"; |
| case DeviceClass::ServiceClass::kObjectTransfer: |
| return "Object Transfer"; |
| case DeviceClass::ServiceClass::kAudio: |
| return "Audio"; |
| case DeviceClass::ServiceClass::kTelephony: |
| return "Telephony"; |
| case DeviceClass::ServiceClass::kInformation: |
| return "Information"; |
| } |
| } |
| |
| } // namespace |
| |
| DeviceClass::DeviceClass() : DeviceClass(MajorClass::kUnspecified) {} |
| |
| DeviceClass::DeviceClass(MajorClass major_class) |
| : bytes_{0x00, static_cast<uint8_t>(major_class), 0x00} {} |
| |
| DeviceClass::DeviceClass(std::initializer_list<uint8_t> bytes) { |
| ZX_DEBUG_ASSERT(bytes.size() == bytes_.size()); |
| std::copy(bytes.begin(), bytes.end(), bytes_.begin()); |
| } |
| |
| DeviceClass::DeviceClass(uint32_t value) { |
| ZX_DEBUG_ASSERT(value < 1 << 24); // field should only populate 24 bits |
| bytes_ = { |
| static_cast<uint8_t>((value >> 0) & 0xFF), |
| static_cast<uint8_t>((value >> 8) & 0xFF), |
| static_cast<uint8_t>((value >> 16) & 0xFF), |
| }; |
| } |
| |
| void DeviceClass::SetServiceClasses(const std::unordered_set<ServiceClass>& classes) { |
| for (const auto& c : classes) { |
| uint8_t bit = static_cast<uint8_t>(c); |
| if (bit >= 16) { |
| bytes_[2] |= 0x01 << (bit - 16); |
| } else if (bit >= 8) { |
| bytes_[1] |= 0x01 << (bit - 8); |
| } |
| } |
| } |
| |
| std::unordered_set<DeviceClass::ServiceClass> DeviceClass::GetServiceClasses() const { |
| std::unordered_set<ServiceClass> classes; |
| for (uint8_t bit_no = 16; bit_no < 24; bit_no++) { |
| if (bytes_[2] & (0x01 << (bit_no - 16))) { |
| classes.emplace(bit_no_to_service_class(bit_no)); |
| } |
| } |
| return classes; |
| } |
| |
| std::string DeviceClass::ToString() const { |
| std::string service_desc; |
| auto classes = GetServiceClasses(); |
| if (!classes.empty()) { |
| auto it = classes.begin(); |
| service_desc = " (" + service_class_to_string(*it); |
| ++it; |
| for (; it != classes.end(); ++it) { |
| service_desc = service_desc + ", " + service_class_to_string(*it); |
| } |
| service_desc = service_desc + ")"; |
| } |
| switch (major_class()) { |
| case MajorClass::kMiscellaneous: |
| return "Miscellaneous" + service_desc; |
| case MajorClass::kComputer: |
| return "Computer" + service_desc; |
| case MajorClass::kPhone: |
| return "Phone" + service_desc; |
| case MajorClass::kLAN: |
| return "LAN" + service_desc; |
| case MajorClass::kAudioVideo: |
| return "A/V" + service_desc; |
| case MajorClass::kPeripheral: |
| return "Peripheral" + service_desc; |
| case MajorClass::kImaging: |
| return "Imaging" + service_desc; |
| case MajorClass::kWearable: |
| return "Wearable" + service_desc; |
| case MajorClass::kToy: |
| return "Toy" + service_desc; |
| case MajorClass::kHealth: |
| return "Health Device" + service_desc; |
| case MajorClass::kUnspecified: |
| return "Unspecified" + service_desc; |
| }; |
| |
| return "(unknown)"; |
| } |
| |
| } // namespace bt |