         maximumTransmissionUnit: ATTMaximumTransmissionUnit = .default,
         maximumPreparedWrites: Int = 50,
         log: ((String) -> ())? = nil,
-        willRead: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ offset: Int) -> ATTError?)? = nil,
-        willWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ newValue: Data) -> ATTError?)? = nil,
-        didWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data) -> Void)? = nil
+        willRead: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ offset: Int) async -> ATTError?)? = nil,
+        willWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ newValue: Data) async -> ATTError?)? = nil,
+        didWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data) async -> Void)? = nil
     ) async {
         // set initial MTU and register handlers
         self.maximumPreparedWrites = maximumPreparedWrites

    
    internal let log: ((String) -> ())?
    
    internal let willRead: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ offset: Int) -> ATTError?)?
    
    internal let willWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ newValue: Data) -> ATTError?)?
    
    internal let didWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data) -> Void)?
    
    // Don't modify
    internal let connection: ATTConnection
    
    internal private(set) var preparedWrites = [PreparedWrite]()

        value = Data(value.prefix(Int(maximumTransmissionUnit.rawValue) - 1))
        
        // validate application errors with read callback
        if let error = await willRead?(attribute.uuid, handle, value, Int(offset)) {
            await errorResponse(opcode, error, handle)
            return nil
        }
