|
| 1 | +package bluetooth |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/hex" |
| 5 | + "strings" |
| 6 | +) |
| 7 | + |
| 8 | +// AttributeProtocolError represents an ATT error code as defined in the |
| 9 | +// Bluetooth Core Specification, Section 3.4.1.1 (ATT_ERROR_RSP), Table 3.4. |
| 10 | +type AttributeProtocolError uint8 |
| 11 | + |
| 12 | +// attErrorDetails holds the name and description for an ATT error code. |
| 13 | +type attErrorDetails struct { |
| 14 | + // name is a short identifier for the error. |
| 15 | + name string |
| 16 | + // description is the human-readable description from the spec. |
| 17 | + description string |
| 18 | +} |
| 19 | + |
| 20 | +// ATT error codes from the Bluetooth Core Specification, Table 3.4. |
| 21 | +const ( |
| 22 | + ErrAttInvalidHandle AttributeProtocolError = 0x01 // The attribute handle given was not valid on this server. |
| 23 | + ErrAttReadNotPermitted AttributeProtocolError = 0x02 // The attribute cannot be read. |
| 24 | + ErrAttWriteNotPermitted AttributeProtocolError = 0x03 // The attribute cannot be written. |
| 25 | + ErrAttInvalidPDU AttributeProtocolError = 0x04 // The attribute PDU was invalid. |
| 26 | + ErrAttInsufficientAuthentication AttributeProtocolError = 0x05 // The attribute requires authentication before it can be read or written. |
| 27 | + ErrAttRequestNotSupported AttributeProtocolError = 0x06 // ATT Server does not support the request received from the client. |
| 28 | + ErrAttInvalidOffset AttributeProtocolError = 0x07 // Offset specified was past the end of the attribute. |
| 29 | + ErrAttInsufficientAuthorization AttributeProtocolError = 0x08 // The attribute requires authorization before it can be read or written. |
| 30 | + ErrAttPrepareQueueFull AttributeProtocolError = 0x09 // Too many prepare writes have been queued. |
| 31 | + ErrAttNotFound AttributeProtocolError = 0x0A // No attribute found within the given attribute handle range. |
| 32 | + ErrAttNotLong AttributeProtocolError = 0x0B // The attribute cannot be read using the ATT_READ_BLOB_REQ PDU. |
| 33 | + ErrAttInsufficientEncKeySize AttributeProtocolError = 0x0C // The Encryption Key Size used for encrypting this link is too short. |
| 34 | + ErrAttInvalidLength AttributeProtocolError = 0x0D // The attribute value length is invalid for the operation. |
| 35 | + ErrAttUnlikelyError AttributeProtocolError = 0x0E // The attribute request has encountered an error that was unlikely, and therefore could not be completed as requested. |
| 36 | + ErrAttInsufficientEncryption AttributeProtocolError = 0x0F // The attribute requires encryption before it can be read or written. |
| 37 | + ErrAttUnsupportedGroupType AttributeProtocolError = 0x10 // The attribute type is not a supported grouping attribute as defined by a higher layer specification. |
| 38 | + ErrAttInsufficientResources AttributeProtocolError = 0x11 // Insufficient Resources to complete the request. |
| 39 | + ErrAttOutOfSync AttributeProtocolError = 0x12 // The server requests the client to rediscover the database. |
| 40 | + ErrAttValueNotAllowed AttributeProtocolError = 0x13 // The attribute parameter value was not allowed. |
| 41 | +) |
| 42 | + |
| 43 | +var attErrors = map[AttributeProtocolError]attErrorDetails{ |
| 44 | + ErrAttInvalidHandle: {"Invalid Handle", "The attribute handle given was not valid on this server."}, |
| 45 | + ErrAttReadNotPermitted: {"Read Not Permitted", "The attribute cannot be read."}, |
| 46 | + ErrAttWriteNotPermitted: {"Write Not Permitted", "The attribute cannot be written."}, |
| 47 | + ErrAttInvalidPDU: {"Invalid PDU", "The attribute PDU was invalid."}, |
| 48 | + ErrAttInsufficientAuthentication: {"Insufficient Authentication", "The attribute requires authentication before it can be read or written."}, |
| 49 | + ErrAttRequestNotSupported: {"Request Not Supported", "ATT Server does not support the request received from the client."}, |
| 50 | + ErrAttInvalidOffset: {"Invalid Offset", "Offset specified was past the end of the attribute."}, |
| 51 | + ErrAttInsufficientAuthorization: {"Insufficient Authorization", "The attribute requires authorization before it can be read or written."}, |
| 52 | + ErrAttPrepareQueueFull: {"Prepare Queue Full", "Too many prepare writes have been queued."}, |
| 53 | + ErrAttNotFound: {"Attribute Not Found", "No attribute found within the given attribute handle range."}, |
| 54 | + ErrAttNotLong: {"Attribute Not Long", "The attribute cannot be read using the ATT_READ_BLOB_REQ PDU."}, |
| 55 | + ErrAttInsufficientEncKeySize: {"Encryption Key Size Too Short", "The Encryption Key Size used for encrypting this link is too short."}, |
| 56 | + ErrAttInvalidLength: {"Invalid Attribute Value Length", "The attribute value length is invalid for the operation."}, |
| 57 | + ErrAttUnlikelyError: {"Unlikely Error", "The attribute request has encountered an error that was unlikely, and therefore could not be completed as requested."}, |
| 58 | + ErrAttInsufficientEncryption: {"Insufficient Encryption", "The attribute requires encryption before it can be read or written."}, |
| 59 | + ErrAttUnsupportedGroupType: {"Unsupported Group Type", "The attribute type is not a supported grouping attribute as defined by a higher layer specification."}, |
| 60 | + ErrAttInsufficientResources: {"Insufficient Resources", "Insufficient Resources to complete the request."}, |
| 61 | + ErrAttOutOfSync: {"Database Out Of Sync", "The server requests the client to rediscover the database."}, |
| 62 | + ErrAttValueNotAllowed: {"Value Not Allowed", "The attribute parameter value was not allowed."}, |
| 63 | +} |
| 64 | + |
| 65 | +// Code returns the raw ATT error code. |
| 66 | +func (e AttributeProtocolError) Code() uint8 { |
| 67 | + return uint8(e) |
| 68 | +} |
| 69 | + |
| 70 | +func (e AttributeProtocolError) details() attErrorDetails { |
| 71 | + if d, ok := attErrors[e]; ok { |
| 72 | + return d |
| 73 | + } |
| 74 | + code := hex.EncodeToString([]byte{uint8(e)}) |
| 75 | + if e >= 0x80 && e <= 0x9F { |
| 76 | + return attErrorDetails{"Application Error", "Application error code defined by a higher layer specification (0x" + code + ")."} |
| 77 | + } |
| 78 | + if e >= 0xE0 && e <= 0xFF { |
| 79 | + return attErrorDetails{"Common Profile and Service Error", "Common profile and service error code (0x" + code + ")."} |
| 80 | + } |
| 81 | + return attErrorDetails{"Reserved", "Reserved for future use (0x" + code + ")."} |
| 82 | +} |
| 83 | + |
| 84 | +// Name returns a short human-readable name for this ATT error code. |
| 85 | +func (e AttributeProtocolError) Name() string { |
| 86 | + return e.details().name |
| 87 | +} |
| 88 | + |
| 89 | +// Description returns the full description from the Bluetooth Core Specification. |
| 90 | +func (e AttributeProtocolError) Description() string { |
| 91 | + return e.details().description |
| 92 | +} |
| 93 | + |
| 94 | +func (e AttributeProtocolError) Error() string { |
| 95 | + d := e.details() |
| 96 | + var b strings.Builder |
| 97 | + b.WriteString("ATT error 0x") |
| 98 | + b.WriteString(hex.EncodeToString([]byte{uint8(e)})) |
| 99 | + b.WriteString(" (") |
| 100 | + b.WriteString(d.name) |
| 101 | + b.WriteString("): ") |
| 102 | + b.WriteString(d.description) |
| 103 | + return b.String() |
| 104 | +} |
0 commit comments