     public func unregisterAll() {
         
         notifyList.removeAll()
+        
         disconnectList.removeAll()
     }
     
     /// Adds a PDU to the queue to send.
     ///
     /// - Returns: Identifier of queued send operation or `nil` if the PDU cannot be sent.
-    public func send<T: ATTProtocolDataUnit>(PDU: T, response: ATTResponseCallback? = nil) -> UInt? {
+    public func send<T: ATTProtocolDataUnit>(PDU: T, response: T -> ()) -> UInt? {
         
         let attributeOpcode = T.attributeOpcode
         
         let type = attributeOpcode.type
-        
-        /* If the opcode corresponds to an operation type that does not elicit a
-        * response from the remote end, then no callback should have been
-        * provided, since it will never be called.
-        */
-        guard (response != nil && type != .Request && type != .Response) == false
-            else { return nil }
-        
-        /* Similarly, if the operation does elicit a response then a callback
-        * must be provided.
-        */
-        guard (response == nil && (type == .Request || type == .Indication)) == false
-            else { return nil }
         
         guard let encodedPDU = encodePDU(PDU)
             else { return nil }
         
         let identifier = nextSendOpcodeID
         
-        let sendOpcode = ATTSendOpcode(identifier: identifier, opcode: attributeOpcode, PDU: encodedPDU, response: response)
+        let sendOpcode = ATTSendOpcode(identifier: identifier, opcode: attributeOpcode, data: encodedPDU, response: response)
         
         // increment ID
         nextSendOpcodeID += 1

    private var nextSendOpcodeID: UInt = 0
    
    /// Pending request state.
    private var pendingRequest: ATTSendOpcode?
    
    /// Pending indication state.
    private var pendingIndication: ATTSendOpcode?
    
    /// Queued ATT protocol requests
    private var requestQueue = Deque<ATTSendOpcode>()
    
    /// Queued ATT protocol indications
    private var indicationQueue = Deque<ATTSendOpcode>()
    
    /// Queue of PDUs ready to send
    private var writeQueue = Deque<ATTSendOpcode>()
    
    /// List of registered callbacks.
    private var notifyList = Deque<ATTNotify>()
    
    /// List of disconnect handlers.
    private var disconnectList = Deque<() -> ()>()

        return data
    }
    
    private func handleResponse(data: Data, opcode: ATT.Opcode) throws {
        
        // If no request is pending, then the response is unexpected. Disconnect the bearer.
        guard let pendingRequest = pendingRequest else {
            
            throw Error.UnexpectedResponse(data)
        }
        
        // If the received response doesn't match the pending request, or if the request is malformed, 
        // end the current request with failure.
        guard pendingRequest.dynamicType.PDUType.attributeOpcode == opcode else {
            
            /*
            // attempt to recover from unexpected error
            guard opcode != ATT.Opcode.ErrorResponse else {
                
                try handleErrorResponse(data, opcode: opcode)
            }*/
            
            throw Error.UnexpectedResponse(data)
        }
        
        // attempt to deserialize
        guard let PDU = pendingRequest.dynamicType.PDUType.init(byteValue: data.byteValue)
            else { throw Error.GarbageResponse(data) }
        
        // success!
        pendingRequest.callback(PDU)
        
        self.pendingRequest = nil
    }
    
    private func handleErrorResponse(data: Data, opcode: ATT.Opcode) throws {
        
        
    }
    
    private func handleConfirmation() {
        
        
    }
    
