/******************************************************************************* ** ** Function gatt_check_write_long_terminate ** ** Description To terminate write long or not. ** ** Returns TRUE: write long is terminated; FALSE keep sending. ** *******************************************************************************/ BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value) { tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; BOOLEAN exec = FALSE; tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC; GATT_TRACE_DEBUG("gatt_check_write_long_terminate "); /* check the first write response status */ if (p_rsp_value != NULL) { if (p_rsp_value->handle != p_attr->handle || p_rsp_value->len != p_clcb->counter || memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len)) { /* data does not match */ p_clcb->status = GATT_ERROR; flag = GATT_PREP_WRITE_CANCEL; exec = TRUE; } else { /* response checking is good */ p_clcb->status = GATT_SUCCESS; /* update write offset and check if end of attribute value */ if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) { exec = TRUE; } } } if (exec) { gatt_send_queue_write_cancel (p_tcb, p_clcb, flag); return TRUE; } return FALSE; }
/******************************************************************************* ** ** Function gatt_process_error_rsp ** ** Description This function is called to handle the error response ** ** ** Returns void ** *******************************************************************************/ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { UINT8 opcode, reason, * p= p_data; UINT16 handle; tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; UNUSED(op_code); UNUSED(len); GATT_TRACE_DEBUG("gatt_process_error_rsp "); STREAM_TO_UINT8(opcode, p); STREAM_TO_UINT16(handle, p); STREAM_TO_UINT8(reason, p); if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) { gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason); } else { if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) && (p_clcb->op_subtype == GATT_WRITE) && (opcode == GATT_REQ_PREPARE_WRITE) && (p_attr) && (handle == p_attr->handle) ) { p_clcb->status = reason; gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL); } else if ((p_clcb->operation == GATTC_OPTYPE_READ) && ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) || (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) && (opcode == GATT_REQ_READ_BLOB) && p_clcb->first_read_blob_after_read && (reason == GATT_NOT_LONG)) { gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); } else gatt_end_operation(p_clcb, reason, NULL); } }