1/****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19#include <arpa/inet.h> 20#include <assert.h> 21#include <string.h> 22 23#include "btcore/include/device_class.h" 24#include "osi/include/osi.h" 25 26typedef struct _bt_device_class_t { 27 uint32_t unused : 2; // LSBs 28 uint32_t minor_device : 6; 29 uint32_t major_device : 5; 30 uint32_t major_service : 11; // MSBs 31} __attribute__ ((__packed__)) _bt_device_class_t; 32 33// Convenience to interpret raw device class bytes. 34#define DC(x) ((_bt_device_class_t *)x) 35 36// Ensure the internal device class implementation and public one 37// have equal size. 38COMPILE_ASSERT(sizeof(_bt_device_class_t) == sizeof(bt_device_class_t)); 39 40// [Major Service Classes](https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband) 41enum { 42 DC_LIMITED_DISCOVERABLE_MODE = 0x0001, 43 DC_RESERVED14 = 0x0002, 44 DC_RESERVED15 = 0x0004, 45 DC_POSITIONING = 0x0008, 46 DC_NETWORKING = 0x0010, 47 DC_RENDERING = 0x0020, 48 DC_CAPTURING = 0x0040, 49 DC_OBJECT_TRANSFER = 0x0080, 50 DC_AUDIO = 0x0100, 51 DC_TELEPHONY = 0x0200, 52 DC_INFORMATION = 0x0400, 53}; 54 55static bool device_class_get_major_service_(const bt_device_class_t *dc, int bitmask); 56static void device_class_clr_major_service_(bt_device_class_t *dc, int bitmask); 57static void device_class_set_major_service_(bt_device_class_t *dc, int bitmask); 58 59void device_class_from_stream(bt_device_class_t *dc, const uint8_t *data) { 60 assert(dc != NULL); 61 assert(data != NULL); 62 *dc = *(bt_device_class_t *)data; 63} 64 65int device_class_to_stream(const bt_device_class_t *dc, uint8_t *data, size_t len) { 66 assert(dc != NULL); 67 assert(data != NULL); 68 assert(len >= sizeof(bt_device_class_t)); 69 for (size_t i = 0; i < sizeof(bt_device_class_t); ++i) { 70 data[i] = dc->_[i]; 71 } 72 return sizeof(bt_device_class_t); 73} 74 75void device_class_from_int(bt_device_class_t *dc, int data) { 76 assert(dc != NULL); 77 assert(data != 0); 78 // Careful with endianess. 79 dc->_[0] = data & 0xff; 80 dc->_[1] = (data >> 8) & 0xff; 81 dc->_[2] = (data >> 16) & 0xff; 82} 83 84int device_class_to_int(const bt_device_class_t *dc) { 85 assert(dc != NULL); 86 // Careful with endianess. 87 return (int)(le32toh(*(int*)dc) & 0xffffff); 88} 89 90bool device_class_equals(const bt_device_class_t *p1, const bt_device_class_t *p2) { 91 assert(p1 != NULL); 92 assert(p2 != NULL); 93 return (memcmp(p1, p2, sizeof(bt_device_class_t)) == 0); 94} 95 96bool device_class_copy(bt_device_class_t *dest, const bt_device_class_t *src) { 97 assert(dest != NULL); 98 assert(src != NULL); 99 return (memcpy(dest, src, sizeof(bt_device_class_t)) == dest); 100} 101 102int device_class_get_major_device(const bt_device_class_t *dc) { 103 assert(dc != NULL); 104 return DC(dc)->major_device; 105} 106 107void device_class_set_major_device(bt_device_class_t *dc, int val) { 108 assert(dc != NULL); 109 DC(dc)->major_device = val; 110} 111 112int device_class_get_minor_device(const bt_device_class_t *dc) { 113 assert(dc != NULL); 114 return DC(dc)->minor_device; 115} 116 117void device_class_set_minor_device(bt_device_class_t *dc, int val) { 118 assert(dc != NULL); 119 DC(dc)->minor_device = val; 120} 121 122bool device_class_get_information(const bt_device_class_t *dc) { 123 assert(dc != NULL); 124 return device_class_get_major_service_(dc, DC_INFORMATION); 125} 126 127void device_class_set_information(bt_device_class_t *dc, bool set) { 128 assert(dc != NULL); 129 if (set) 130 device_class_set_major_service_(dc, DC_INFORMATION); 131 else 132 device_class_clr_major_service_(dc, DC_INFORMATION); 133} 134 135bool device_class_get_limited(const bt_device_class_t *dc) { 136 assert(dc != NULL); 137 return device_class_get_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE); 138} 139 140void device_class_set_limited(bt_device_class_t *dc, bool set) { 141 assert(dc != NULL); 142 if (set) 143 device_class_set_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE); 144 else 145 device_class_clr_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE); 146} 147 148static bool device_class_get_major_service_(const bt_device_class_t *dc, int bitmask) { 149 return (DC(dc)->major_service & bitmask); 150} 151 152static void device_class_clr_major_service_(bt_device_class_t *dc, int bitmask) { 153 DC(dc)->major_service &= ~bitmask; 154} 155 156static void device_class_set_major_service_(bt_device_class_t *dc, int bitmask) { 157 DC(dc)->major_service |= bitmask; 158} 159