diff --git a/src/BLECharacteristic.cpp b/src/BLECharacteristic.cpp index bfaee3ff..2fbd9b94 100644 --- a/src/BLECharacteristic.cpp +++ b/src/BLECharacteristic.cpp @@ -236,6 +236,32 @@ int BLECharacteristic::readValue(int32_t& value) return readValue((uint8_t*)&value, sizeof(value)); } +int BLECharacteristic::write(const char* value, bool withResponse) +{ + if (_local) { + return _local->write(value); + } + + if (_remote) { + return _remote->write(value, withResponse); + } + + return 0; +} + +int BLECharacteristic::write(const uint8_t value[], int length, bool withResponse) +{ + if (_local) { + return _local->write(value, length); + } + + if (_remote) { + return _remote->write(value, length, withResponse); + } + + return 0; +} + int BLECharacteristic::writeValue(const uint8_t value[], int length, bool withResponse) { if (_local) { diff --git a/src/BLECharacteristic.h b/src/BLECharacteristic.h index da9721e0..8c117b25 100644 --- a/src/BLECharacteristic.h +++ b/src/BLECharacteristic.h @@ -77,6 +77,9 @@ class BLECharacteristic { int writeValue(int16_t value, bool withResponse = true); int writeValue(uint32_t value, bool withResponse = true); int writeValue(int32_t value, bool withResponse = true); + int write(const uint8_t value[], int length, bool withResponse = true); + int write(const char* value, bool withResponse = true); + // deprecated, use writeValue(...) int setValue(const uint8_t value[], int length) { return writeValue(value, length); } diff --git a/src/local/BLELocalCharacteristic.cpp b/src/local/BLELocalCharacteristic.cpp index 207425bd..105d71bc 100644 --- a/src/local/BLELocalCharacteristic.cpp +++ b/src/local/BLELocalCharacteristic.cpp @@ -119,9 +119,9 @@ int BLELocalCharacteristic::writeValue(const uint8_t value[], int length) } if ((_properties & BLEIndicate) && (_cccdValue & 0x0002)) { - return ATT.handleInd(valueHandle(), _value, _valueLength); + return ATT.handleInd(valueHandle(), _value,&_valueLength); } else if ((_properties & BLENotify) && (_cccdValue & 0x0001)) { - return ATT.handleNotify(valueHandle(), _value, _valueLength); + return ATT.handleNotify(valueHandle(), _value, &_valueLength); } if (_broadcast) { @@ -142,6 +142,47 @@ int BLELocalCharacteristic::writeValue(const char* value) return writeValue((uint8_t*)value, strlen(value)); } +int BLELocalCharacteristic::write(const uint8_t value[], int length) +{ + _valueLength = min(length, _valueSize); + memcpy(_value, value, _valueLength); + + if (_fixedLength) { + _valueLength = _valueSize; + } + + if ((_properties & BLEIndicate) && (_cccdValue & 0x0002)) { + uint8_t res = ATT.handleInd(valueHandle(), _value, &_valueLength); + if (res != 1){ + return res; + } + return _valueLength; + } else if ((_properties & BLENotify) && (_cccdValue & 0x0001)) { + uint8_t res = ATT.handleNotify(valueHandle(), _value, &_valueLength); + if (res != 1){ + return res; + } + return _valueLength; + } + + if (_broadcast) { + uint16_t serviceUuid = GATT.serviceUuidForCharacteristic(this); + + BLE.setAdvertisedServiceData(serviceUuid, value, length); + + if (!ATT.connected() && GAP.advertising()) { + BLE.advertise(); + } + } + + return _valueLength; +} + +int BLELocalCharacteristic::write(const char* value) +{ + return write((uint8_t*)value, strlen(value)); +} + int BLELocalCharacteristic::broadcast() { if (_properties & BLEBroadcast) { diff --git a/src/local/BLELocalCharacteristic.h b/src/local/BLELocalCharacteristic.h index 331cdd5c..c73d0512 100644 --- a/src/local/BLELocalCharacteristic.h +++ b/src/local/BLELocalCharacteristic.h @@ -49,6 +49,8 @@ class BLELocalCharacteristic : public BLELocalAttribute { int writeValue(const uint8_t value[], int length); int writeValue(const char* value); + int write(const uint8_t value[], int length); + int write(const char* value); int broadcast(); diff --git a/src/remote/BLERemoteCharacteristic.cpp b/src/remote/BLERemoteCharacteristic.cpp index 454438b6..52dc480b 100644 --- a/src/remote/BLERemoteCharacteristic.cpp +++ b/src/remote/BLERemoteCharacteristic.cpp @@ -86,6 +86,59 @@ uint8_t BLERemoteCharacteristic::operator[] (int offset) const return 0; } +int BLERemoteCharacteristic::write(const uint8_t value[], int length, bool withResponse) +{ + if (!ATT.connected(_connectionHandle)) { + return false; + } + + uint16_t maxLength = ATT.mtu(_connectionHandle) - 3; + + if (length > (int)maxLength) { + // cap to MTU max length + length = maxLength; + } + + _value = (uint8_t*)realloc(_value, length); + if (_value == NULL) { + // realloc failed + return 0; + } + + if ((_properties & BLEWrite) && withResponse) { + uint8_t resp[4]; + int respLength = ATT.writeReq(_connectionHandle, _valueHandle, value, length, resp); + + if (!respLength) { + return 0; + } + + if (resp[0] == 0x01) { + // error + return 0; + } + + memcpy(_value, value, length); + _valueLength = length; + + return length; + } else if (_properties & BLEWriteWithoutResponse) { + ATT.writeCmd(_connectionHandle, _valueHandle, value, length); + + memcpy(_value, value, length); + _valueLength = length; + + return length; + } + + return 0; +} + +int BLERemoteCharacteristic::write(const char* value, bool withResponse) +{ + return write((uint8_t*)value, strlen(value), withResponse); +} + int BLERemoteCharacteristic::writeValue(const uint8_t value[], int length, bool withResponse) { if (!ATT.connected(_connectionHandle)) { diff --git a/src/remote/BLERemoteCharacteristic.h b/src/remote/BLERemoteCharacteristic.h index b53ab031..9b2e493c 100644 --- a/src/remote/BLERemoteCharacteristic.h +++ b/src/remote/BLERemoteCharacteristic.h @@ -41,6 +41,8 @@ class BLERemoteCharacteristic : public BLERemoteAttribute { int writeValue(const uint8_t value[], int length, bool withResponse = true); int writeValue(const char* value, bool withResponse = true); + int write(const uint8_t value[], int length, bool withResponse = true); + int write(const char* value, bool withResponse = true); bool valueUpdated(); bool updatedValueRead(); diff --git a/src/utility/ATT.cpp b/src/utility/ATT.cpp index b1796c90..84ecf7f7 100644 --- a/src/utility/ATT.cpp +++ b/src/utility/ATT.cpp @@ -582,7 +582,7 @@ BLEDevice ATTClass::central() return BLEDevice(); } -bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length) +bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, uint16_t *length) { int numNotifications = 0; @@ -600,9 +600,9 @@ bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length) memcpy(¬ification[1], &handle, sizeof(handle)); notificationLength += sizeof(handle); - length = min((uint16_t)(_peers[i].mtu - notificationLength), (uint16_t)length); - memcpy(¬ification[notificationLength], value, length); - notificationLength += length; + *length = min((uint16_t)(_peers[i].mtu - notificationLength), *length); + memcpy(¬ification[notificationLength], value, *length); + notificationLength += *length; /// TODO: Set encryption requirement on notify. HCI.sendAclPkt(_peers[i].connectionHandle, ATT_CID, notificationLength, notification); @@ -613,7 +613,7 @@ bool ATTClass::handleNotify(uint16_t handle, const uint8_t* value, int length) return (numNotifications > 0); } -bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, int length) +bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, uint16_t *length) { int numIndications = 0; @@ -631,9 +631,10 @@ bool ATTClass::handleInd(uint16_t handle, const uint8_t* value, int length) memcpy(&indication[1], &handle, sizeof(handle)); indicationLength += sizeof(handle); - length = min((uint16_t)(_peers[i].mtu - indicationLength), (uint16_t)length); - memcpy(&indication[indicationLength], value, length); - indicationLength += length; + *length = min((uint16_t)(_peers[i].mtu - indicationLength), *length); + + memcpy(&indication[indicationLength], value, *length); + indicationLength += *length; _cnf = false; diff --git a/src/utility/ATT.h b/src/utility/ATT.h index c9f007f9..2f478a7d 100644 --- a/src/utility/ATT.h +++ b/src/utility/ATT.h @@ -83,8 +83,8 @@ class ATTClass { virtual BLEDevice central(); - virtual bool handleNotify(uint16_t handle, const uint8_t* value, int length); - virtual bool handleInd(uint16_t handle, const uint8_t* value, int length); + virtual bool handleNotify(uint16_t handle, const uint8_t* value, uint16_t *length); + virtual bool handleInd(uint16_t handle, const uint8_t* value, uint16_t *length); virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);