mbed-os/features/FEATURE_BLE/ble/pal/AttServerMessage.h

772 lines
24 KiB
C
Raw Normal View History

/* mbed Microcontroller Library
* Copyright (c) 2017-2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BLE_PAL_ATT_SERVER_MESSAGE_H_
#define BLE_PAL_ATT_SERVER_MESSAGE_H_
#include "ble/BLETypes.h"
#include "ble/ArrayView.h"
namespace ble {
namespace pal {
/**
* Operation code defined for attribute operations
* @note see: BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.8
*/
struct AttributeOpcode {
enum Code {
ERROR_RESPONSE = 0x01, /// Opcode of an AttErrorResponse
EXCHANGE_MTU_REQUEST = 0x02,
EXCHANGE_MTU_RESPONSE = 0x03, /// OpCode of an AttExchangeMTUResponse
FIND_INFORMATION_REQUEST = 0x04,
FIND_INFORMATION_RESPONSE = 0x05, /// OpCode of an AttFindInformationResponse
FIND_BY_TYPE_VALUE_REQUEST = 0x06,
FIND_BY_VALUE_TYPE_RESPONSE = 0x07, /// OpCode of an AttFindByTypeValueResponse
READ_BY_TYPE_REQUEST = 0x08,
READ_BY_TYPE_RESPONSE = 0x09, /// Opcode of an AttReadByTypeResponse
READ_REQUEST = 0x0A,
READ_RESPONSE = 0x0B, /// Opcode of an AttReadResponse
READ_BLOB_REQUEST = 0x0C,
READ_BLOB_RESPONSE = 0x0D, /// Opcode of an AttReadBlobResponse
READ_MULTIPLE_REQUEST = 0x0E,
READ_MULTIPLE_RESPONSE = 0x0F, /// Opcode of an AttReadMultipleResponse
READ_BY_GROUP_TYPE_REQUEST = 0x10,
READ_BY_GROUP_TYPE_RESPONSE = 0x11, /// Opcode of an AttReadByGroupTypeResponse
WRITE_REQUEST = 0x12,
WRITE_RESPONSE = 0x13, /// Opcode of an AttWriteResponse
WRITE_COMMAND = 0x52,
SIGNED_WRITE_COMMAND = 0xD2,
PREPARE_WRITE_REQUEST = 0x16,
PREPARE_WRITE_RESPONSE = 0x17, /// Opcode of an AttPrepareWriteResponse
EXECUTE_WRITE_REQUEST = 0x18,
EXECUTE_WRITE_RESPONSE = 0x19, /// Opcode of an AttExecuteWriteResponse
HANDLE_VALUE_NOTIFICATION = 0x1B,
HANDLE_VALUE_INDICATION = 0x1D
};
/**
* Construct an AttributeOpcode from a Code.
*/
AttributeOpcode(Code value) : _value(value) { }
/**
* Equality comparison operator between two AttributeOpcode
*/
friend bool operator==(AttributeOpcode lhs, AttributeOpcode rhs) {
return lhs._value == rhs._value;
}
/**
* Non equality comparison operator between two AttributeOpcode
*/
friend bool operator!=(AttributeOpcode lhs, AttributeOpcode rhs) {
return lhs._value != rhs._value;
}
/**
* implicit cast to uint8_t.
* Allows AttributeOpcode to be used in switch statements.
*/
operator uint8_t() const {
return _value;
}
private:
uint8_t _value;
};
/**
* Base class for Attribute Server Message.
* The correct type of the instance can be determined with the attribute opcode.
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1
*/
struct AttServerMessage {
/**
* Op code used to identify the type of the attribute response.
*/
const AttributeOpcode opcode;
protected:
/**
* Construction of an AttResponse is reserved for descendent of the class
*/
AttServerMessage(AttributeOpcode opcode_) : opcode(opcode_) { }
};
/**
* Response to a request which can't be performed
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.1.1
* for details about error response.
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.9
* which details possible error response by requests.
*/
struct AttErrorResponse : public AttServerMessage {
/**
* Construct an attribute error response.
*
* @param request_opcode_ The Attribute opcode of the request that generated
* the error.
* @param handle_in_error_ The attribute handle that generated this error
* response.
* @param error_code The reason why the request has generated an error.
*/
AttErrorResponse(
AttributeOpcode request_opcode_,
attribute_handle_t handle_in_error_,
uint8_t error_code_
) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE),
request_opcode(request_opcode_),
handle_in_error(handle_in_error_), error_code(error_code_) {
}
/**
* Construct an attribute error response in the case where there was no
* attribute handle in the original response or if the request is not
* supported.
*
* @param request_opcode_ The Attribute opcode of the request that generated
* the error.
* @param error_code The reason why the request has generated an error.
*/
AttErrorResponse(
AttributeOpcode request_opcode_,
uint8_t error_code_
) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE),
request_opcode(request_opcode_),
handle_in_error(0x0000), error_code(error_code_) {
}
/**
* The opcode of the request that generated this error response.
*/
const AttributeOpcode request_opcode;
/**
* The attribute handle that generated this error response.
* If there was no attribute handle in the original request or if the
* request is not supported, then this field is equal to 0x0000.
*/
const attribute_handle_t handle_in_error;
/**
* The reason why the request has generated an error response
*/
const uint8_t error_code;
/**
* List of Error codes for the ATT protocol
*/
enum AttributeErrorCode {
/** The attribute handle given was not valid on this server. */
INVALID_HANDLE = 0x01,
/** The attribute cannot be read. */
READ_NOT_PERMITTED = 0x02,
/** The attribute cannot be written. */
WRITE_NOT_PERMITTED = 0x03,
/** The attribute PDU was invalid. */
INVALID_PDU = 0x04,
/** The attribute requires authentication before it can be read or
* written.
*/
INSUFFICIENT_AUTHENTICATION = 0x05,
/** Attribute server does not support the request received from the
* client.
*/
REQUEST_NOT_SUPPORTED = 0x06,
/** Offset specified was past the end of the attribute. */
INVALID_OFFSET = 0x07,
/** The attribute requires authorization before it can be read or written. */
INSUFFICIENT_AUTHORIZATION = 0x08,
/** Too many prepare writes have been queued. */
PREPARE_QUEUE_FULL = 0x09,
/** No attribute found within the given attribute handle range. */
ATTRIBUTE_NOT_FOUND = 0x0A,
/** The attribute cannot be read using the Read Blob Request. */
ATTRIBUTE_NOT_LONG = 0x0B,
/** The Encryption Key Size used for encrypting this link is
* insufficient.
*/
INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0C,
/** The attribute value length is invalid for the operation. */
INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0D,
/** The attribute request that was requested has encountered an error
* that was unlikely, and therefore could not be completed as requested.
*/
UNLIKELY_ERROR = 0x0E,
/** The attribute requires encryption before it can be read or written. */
INSUFFICIENT_ENCRYPTION = 0x0F,
/** The attribute type is not a supported grouping attribute as defined
* by a higher layer specification.
*/
UNSUPPORTED_GROUP_TYPE = 0x10,
/** Insufficient Resources to complete the request. */
INSUFFICIENT_RESOURCES = 0x11,
/* 0x12 - 0x7F => reserved for future use */
/* 0x80 - 0x9F => Application Error */
/* 0xA0 0xDF => Reserved for future use */
/* 0xE0 - 0xFF Common Profile and service Error Codes */
/** The Write Request Rejected error code is used when a requested write
* operation cannot be fulfilled for reasons other than permissions.
*/
WRITE_REQUEST_REJECTED = 0xFC,
/** The Client Characteristic Configuration Descriptor Improperly
* Configured error code is used when a Client Characteristic
* Configuration descriptor is not configured according to the
* requirements of the profile or service.
*/
CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED = 0xFD,
/** The Procedure Already in Progress error code is used when a profile
* or service request cannot be serviced because an operation that has
* been previously triggered is still in progress
*/
PROCEDURE_ALREADY_IN_PROGRESS = 0xFE,
/** The Out of Range error code is used when an attribute value is out
* of range as defined by a profile or service specification.
*/
OUT_OF_RANGE = 0xFF
};
};
/**
* The Exchange MTU Request is used by the client to inform the server of the
* clients maximum receive MTU size and request the server to respond with its
* maximum rx MTU size.
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.2
*/
struct AttExchangeMTUResponse : public AttServerMessage {
/**
* Construct an exchange mtu response containing the max rx mtu of the
* server.
*
* @param server_rx_mtu_ The max rx mtu the server can handle.
*/
AttExchangeMTUResponse(uint16_t server_rx_mtu_) :
AttServerMessage(AttributeOpcode::EXCHANGE_MTU_RESPONSE),
server_rx_mtu(server_rx_mtu_) {
}
/**
* The max rx mtu the server can handle.
*/
const uint16_t server_rx_mtu;
};
/**
* The Find Information Response is sent in reply to a received Find Information
* Request and contains information about this server.
*
* The Find Information Response contains a sequence of handle-uuid pairs in
* ascending order if attribute handles.
*
* This class has to be subclassed by an implementation specific class defining
* the member function size and the subscript operator.
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.2
*/
struct AttFindInformationResponse : public AttServerMessage {
/** handle-uuid pair */
struct information_data_t {
attribute_handle_t handle;
UUID uuid;
};
/**
* Base constructor, setup the OpCode of the response.
*/
AttFindInformationResponse() :
AttServerMessage(AttributeOpcode::FIND_INFORMATION_RESPONSE) {
}
/**
* virtual destructor to overide if the sub class needs it.
*/
virtual ~AttFindInformationResponse() { }
/**
* Returns the number of information_data_t present in the response.
*/
virtual size_t size() const = 0;
/**
* Access to information_data_t elements present in the response.
* @note Out of range access is undefined.
*/
virtual information_data_t operator[](size_t index) const = 0;
};
/**
* Find by type value responses are sent in response to find by type value
* request.
*
* The response contains a sequence of Found Attribute Handle, Group End Handle
* pair where:
* - Found Attribute Handle is the handle of an attribute matching the type
* and the value requested.
* - Group End Handle is the end of the attribute group if the attribute found
* is a grouping attribute or the same value as Found Attribute Handle if
* the attribute is not a grouping attribute.
*
* This class should be subclassed by an implementation specific class defining
* the member function size and the subscript operator.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.4
*/
struct AttFindByTypeValueResponse : public AttServerMessage {
/**
* Base constructor, setup the OpCode of the response.
*/
AttFindByTypeValueResponse() :
AttServerMessage(AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE) {
}
/**
* virtual destructor to overide if the sub class needs it.
*/
virtual ~AttFindByTypeValueResponse() { }
/**
* Returns the number of attribute_handle_range_t present in the response.
*/
virtual std::size_t size() const = 0;
/**
* Access to the attribute range present in the response.
* @note Out of range access is undefined.
*/
virtual attribute_handle_range_t operator[](size_t index) const = 0;
};
/**
* Response to a Read By Type request.
*
* It contains a list of handle-value pairs where:
* - handle is the handle of the attribute matching the rype requested.
* - value is the value of the attribute found. If the value is longer than
* (mtu - 4) then it can be truncated and read blob request should be used
* to read the remaining octet of the attribute.
*
* This class has to be subclassed by an implementation specific class defining
* the member function size and the subscript operator.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.2
*/
struct AttReadByTypeResponse : public AttServerMessage {
/**
* handle-value pair
*/
struct attribute_data_t {
attribute_handle_t handle;
ArrayView<const uint8_t> value;
};
/**
* Base constructor, setup the OpCode of the response.
*/
AttReadByTypeResponse() :
AttServerMessage(AttributeOpcode::READ_BY_TYPE_RESPONSE) {
}
/**
* virtual destructor to overide if the sub class needs it.
*/
virtual ~AttReadByTypeResponse() { }
/**
* Return the number of attribute_data_t presents in the response.
*/
virtual size_t size() const = 0;
/**
* Return the attribute data at index.
* @note Out of range access is undefined.
*/
virtual attribute_data_t operator[](size_t index) const = 0;
};
/**
* The read response is sent in reply to a received Read Request and contains
* the value of the attribute that has been read.
*
* The attribute value shall be set to the value of the attribute identified by
* the attribute handle in the request. If the attribute value is longer than
* (ATT_MTU-1) then the first (ATT_MTU-1) octets shall be included in this
* response.
*
* @note The Read Blob Request would be used to read the remaining octets of a
* long attribute value.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.4
*/
struct AttReadResponse : public AttServerMessage {
/**
* Construct a Read Response from an array of bytes.
*/
AttReadResponse(ArrayView<const uint8_t> data_) :
AttServerMessage(AttributeOpcode::READ_RESPONSE), _data(data_) {
}
/**
* Return the number of octets presents in the response.
*/
size_t size() const {
return _data.size();
}
/**
* Return the octet at the specified index.
* @note Out of range access is undefined.
*/
uint8_t operator[](size_t index) const {
return _data[index];
}
/**
* Return the pointer to the actual data
*/
const uint8_t* data() const {
return _data.data();
}
private:
const ArrayView<const uint8_t> _data;
};
/**
* The Read Blob Response is sent in reply to a received Read Blob Request and
* contains part of the value of the attribute that has been read.
*
* If the offset requested is equal to the length of the attribute then the
* response contains no data and the size of the data returned is equal to 0.
*
* If the value of the attribute starting at the offset requested is longer than
* (mtu - 1) octets then the first (mtu - 1) will be present in the response.
* The remaining octets will be acquired by another Read Blob Request with an
* updated index.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.6
*/
struct AttReadBlobResponse : public AttServerMessage {
/**
* Construct a read blob response from the value responded.
*/
AttReadBlobResponse(ArrayView<const uint8_t> data_) :
AttServerMessage(AttributeOpcode::READ_BLOB_RESPONSE), _data(data_) {
}
/**
* Return the number of octets presents in the response value.
*/
size_t size() const {
return _data.size();
}
/**
* Return the octet of the value read at the specified index.
* @note Out of range access is undefined.
*/
uint8_t operator[](size_t index) const {
return _data[index];
}
/**
* Return the pointer to the actual data
*/
const uint8_t* data() const {
return _data.data();
}
private:
const ArrayView<const uint8_t> _data;
};
/**
* Response to a Read Multiple Request. It contains the values of the attributes
* that have been read.
*
* If the set of values that has been read is longer than (mtu - 1) then only
* the first (mtu - 1) octets are included in the response.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.8
*/
struct AttReadMultipleResponse : public AttServerMessage {
/**
* Construct a Resd Multiple Response from the set of value received.
*/
AttReadMultipleResponse(ArrayView<const uint8_t> data_) :
AttServerMessage(AttributeOpcode::READ_MULTIPLE_RESPONSE), _data(data_) {
}
/**
* Return the number of octets presents in the response set of value.
*/
size_t size() const {
return _data.size();
}
/**
* Return the octet of the set of value read at the specified index.
* @note Out of range access is undefined.
*/
uint8_t operator[](size_t index) const {
return _data[index];
}
private:
const ArrayView<const uint8_t> _data;
};
/**
* The Read By Group Type Response is sent in reply to a received Read By
* Group Type Request and contains the handles and values of the attributes that
* have been read.
*
* The response is a list of group range-value pair where:
* - group range: The range of the group found where begin is the grouping
* attribute handle and end is the handle of the end of the group.
* - value: The value of the grouping attribute.
*
* This class has to be subclassed by an implementation specific class defining
* the member function size and the subscript operator.
*
* @note The value responded can be trucated if it doesn't fit in the response,
* in that case a Read Blob Request could be used to read the remaining octets.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.10
*/
struct AttReadByGroupTypeResponse : public AttServerMessage {
/**
* Data read from the grouping attribute.
* It includes the range of the group and the value of the attribute.
*/
struct attribute_data_t {
attribute_handle_range_t group_range;
ArrayView<const uint8_t> value;
};
/**
* Base constructor, setup the OpCode of the response.
*/
AttReadByGroupTypeResponse() :
AttServerMessage(AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE) {
}
/**
* virtual destructor to overide if the sub class needs it.
*/
virtual ~AttReadByGroupTypeResponse() { }
/**
* Return the number of attribute_data_t present in the response.
*/
virtual size_t size() const = 0;
/**
* Return the attribute data read at the index specified.
* @note Out of range access is undefined.
*/
virtual attribute_data_t operator[](size_t index) const = 0;
};
/**
* The Write Response is sent in reply to a valid Write Request and
* acknowledges that the attribute has been successfully written.
* It is just a placeholder which indicates the client that the write request
* was successful.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.2
*/
struct AttWriteResponse : public AttServerMessage {
/**
* Construct a write response.
*/
AttWriteResponse() : AttServerMessage(AttributeOpcode::WRITE_RESPONSE) { }
};
/**
* Response to a Prepare Write Request. It acknowledges the client that the
* value has been successfully received and placed in the write queue.
*
* The response contains the same values as the one present in the request.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.2
*/
struct AttPrepareWriteResponse : public AttServerMessage {
/**
* Construct a prepare write response.
* @param handle_ The handle of the attribute to be written.
* @param offset_: The offset of the first octet to be writen.
* @param value_: The value of the attribute to be written at the offset
* indicated.
*/
AttPrepareWriteResponse(
attribute_handle_t handle_,
uint16_t offset_,
ArrayView<const uint8_t> value_
) : AttServerMessage(AttributeOpcode::PREPARE_WRITE_RESPONSE),
attribute_handle(handle_),
offset(offset_),
partial_value(value_) {
}
/**
* The handle of the attribute to be written.
*/
const attribute_handle_t attribute_handle;
/**
* The offset of the first octet to be writen.
*/
const uint16_t offset;
/**
* The value of the attribute to be written at the offset indicated.
*/
const ArrayView<const uint8_t> partial_value;
};
/**
* The Execute Write Response is sent in response to a received Execute Write
* Request.
*
* It is just a placeholder which indicates the client that the execution of the
* write request has been successfull.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.4
*/
struct AttExecuteWriteResponse : public AttServerMessage {
/**
* Construct an execute write response object.
*/
AttExecuteWriteResponse() :
AttServerMessage(AttributeOpcode::EXECUTE_WRITE_RESPONSE) {
}
};
/**
* Notification of an attribute's value sent by the server.
*
* It contains the handle of the attribute and its value.
*
* If the attribute value is longer than (mtu - 3) then the value is truncated
* to (mtu - 3) octets to fit in the response and the client will have to use
* a read blob request to read the remaining octets of the attribute.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.1
*/
struct AttHandleValueNotification : public AttServerMessage {
/**
* Construct an Handle Value Notification from the attribute handle and its
* value notified.
*/
AttHandleValueNotification(
attribute_handle_t attribute_handle,
ArrayView<const uint8_t> attribute_value
) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_NOTIFICATION),
attribute_handle(attribute_handle),
attribute_value(attribute_value) {
}
/**
* Handle of the attribute
*/
const attribute_handle_t attribute_handle;
/**
* The current value of the attribute.
*/
const ArrayView<const uint8_t> attribute_value;
};
/**
* Indication of an attribute's value sent by the server.
*
* It contains the handle of the attribute and its value. The client should
* respond with and handle value confirmation.
*
* If the attribute value is longer than (mtu - 3) then the value is truncated
* to (mtu - 3) octets to fit in the response and the client will have to use
* a read blob request to read the remaining octets of the attribute.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.2
*/
struct AttHandleValueIndication : public AttServerMessage {
/**
* Construct an Handle Value Indication from the attribute handle and its
* value indicated.
*/
AttHandleValueIndication(
attribute_handle_t handle, ArrayView<const uint8_t> value
) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_INDICATION),
attribute_handle(handle), attribute_value(value) {
}
/**
* Handle of the attribute
*/
const attribute_handle_t attribute_handle;
/**
* The current value of the attribute.
*/
const ArrayView<const uint8_t> attribute_value;
};
} // namespace pal
} // namespace ble
#endif /* BLE_PAL_ATT_SERVER_MESSAGE_H_ */