<commit_before>#include <uds/uds.h>
#include <bitfield/bitfield.h>
#include <canutil/read.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <sys/param.h>
#include <inttypes.h>

#define ARBITRATION_ID_OFFSET 0x8
#define MODE_RESPONSE_OFFSET 0x40
#define NEGATIVE_RESPONSE_MODE 0x7f
#define MAX_DIAGNOSTIC_PAYLOAD_SIZE 6
#define MODE_BYTE_INDEX 0
#define PID_BYTE_INDEX 1
#define NEGATIVE_RESPONSE_MODE_INDEX 1
#define NEGATIVE_RESPONSE_NRC_INDEX 2

#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif

DiagnosticShims diagnostic_init_shims(LogShim log,
        SendCanMessageShim send_can_message,
        SetTimerShim set_timer) {
    DiagnosticShims shims = {
        log: log,
        send_can_message: send_can_message,
        set_timer: set_timer
    };
    return shims;
}

static void setup_receive_handle(DiagnosticRequestHandle* handle) {
    if(handle->request.arbitration_id == OBD2_FUNCTIONAL_BROADCAST_ID) {
        uint32_t response_id;
        for(response_id = 0;
                response_id < OBD2_FUNCTIONAL_RESPONSE_COUNT; ++response_id) {
            handle->isotp_receive_handles[response_id] = isotp_receive(
                    &handle->isotp_shims,
                    OBD2_FUNCTIONAL_RESPONSE_START + response_id,
                    NULL);
        }
        handle->isotp_receive_handle_count = OBD2_FUNCTIONAL_RESPONSE_COUNT;
    } else {
        handle->isotp_receive_handle_count = 1;
        handle->isotp_receive_handles[0] = isotp_receive(&handle->isotp_shims,
                handle->request.arbitration_id + ARBITRATION_ID_OFFSET,
                NULL);
    }
}

static uint16_t autoset_pid_length(uint8_t mode, uint16_t pid,
        uint8_t pid_length) {
    if(pid_length == 0) {
        if(pid > 0xffff || (mode != 0x3e && mode > 0xa)) {
            pid_length = 2;
        } else {
            pid_length = 1;
        }
    }
    return pid_length;
}

static void send_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequestHandle* handle) {
    uint8_t payload[MAX_DIAGNOSTIC_PAYLOAD_SIZE] = {0};
    payload[MODE_BYTE_INDEX] = handle->request.mode;
    if(handle->request.has_pid) {
        handle->request.pid_length = autoset_pid_length(handle->request.mode,
                handle->request.pid, handle->request.pid_length);
        handle->request.pid_length = handle->request.pid_length;
        set_bitfield(handle->request.pid, PID_BYTE_INDEX * CHAR_BIT,
                handle->request.pid_length * CHAR_BIT, payload,
                sizeof(payload));
    }

    if(handle->request.payload_length > 0) {
        memcpy(&payload[PID_BYTE_INDEX + handle->request.pid_length],
                handle->request.payload, handle->request.payload_length);
    }

    handle->isotp_send_handle = isotp_send(&handle->isotp_shims,
            handle->request.arbitration_id, payload,
            1 + handle->request.payload_length + handle->request.pid_length,
            NULL);
    if(shims->log != NULL) {
        char request_string[128] = {0};
        diagnostic_request_to_string(&handle->request, request_string,
                sizeof(request_string));
        shims->log("Sending diagnostic request: %s", request_string);
    }
}

bool diagnostic_request_sent(DiagnosticRequestHandle* handle) {
    return handle->isotp_send_handle.completed;
}

void start_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequestHandle* handle) {
    handle->success = false;
    handle->completed = false;
    send_diagnostic_request(shims, handle);
    setup_receive_handle(handle);
}

DiagnosticRequestHandle generate_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequest* request, DiagnosticResponseReceived callback) {
    DiagnosticRequestHandle handle = {
        request: *request,
        callback: callback,
        success: false,<commit_msg>Propagate errors from isotp-c when sending requests.<commit_after>#include <uds/uds.h>
#include <bitfield/bitfield.h>
#include <canutil/read.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <sys/param.h>
#include <inttypes.h>

#define ARBITRATION_ID_OFFSET 0x8
#define MODE_RESPONSE_OFFSET 0x40
#define NEGATIVE_RESPONSE_MODE 0x7f
#define MAX_DIAGNOSTIC_PAYLOAD_SIZE 6
#define MODE_BYTE_INDEX 0
#define PID_BYTE_INDEX 1
#define NEGATIVE_RESPONSE_MODE_INDEX 1
#define NEGATIVE_RESPONSE_NRC_INDEX 2

#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif

DiagnosticShims diagnostic_init_shims(LogShim log,
        SendCanMessageShim send_can_message,
        SetTimerShim set_timer) {
    DiagnosticShims shims = {
        log: log,
        send_can_message: send_can_message,
        set_timer: set_timer
    };
    return shims;
}

static void setup_receive_handle(DiagnosticRequestHandle* handle) {
    if(handle->request.arbitration_id == OBD2_FUNCTIONAL_BROADCAST_ID) {
        uint32_t response_id;
        for(response_id = 0;
                response_id < OBD2_FUNCTIONAL_RESPONSE_COUNT; ++response_id) {
            handle->isotp_receive_handles[response_id] = isotp_receive(
                    &handle->isotp_shims,
                    OBD2_FUNCTIONAL_RESPONSE_START + response_id,
                    NULL);
        }
        handle->isotp_receive_handle_count = OBD2_FUNCTIONAL_RESPONSE_COUNT;
    } else {
        handle->isotp_receive_handle_count = 1;
        handle->isotp_receive_handles[0] = isotp_receive(&handle->isotp_shims,
                handle->request.arbitration_id + ARBITRATION_ID_OFFSET,
                NULL);
    }
}

static uint16_t autoset_pid_length(uint8_t mode, uint16_t pid,
        uint8_t pid_length) {
    if(pid_length == 0) {
        if(pid > 0xffff || (mode != 0x3e && mode > 0xa)) {
            pid_length = 2;
        } else {
            pid_length = 1;
        }
    }
    return pid_length;
}

static void send_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequestHandle* handle) {
    uint8_t payload[MAX_DIAGNOSTIC_PAYLOAD_SIZE] = {0};
    payload[MODE_BYTE_INDEX] = handle->request.mode;
    if(handle->request.has_pid) {
        handle->request.pid_length = autoset_pid_length(handle->request.mode,
                handle->request.pid, handle->request.pid_length);
        handle->request.pid_length = handle->request.pid_length;
        set_bitfield(handle->request.pid, PID_BYTE_INDEX * CHAR_BIT,
                handle->request.pid_length * CHAR_BIT, payload,
                sizeof(payload));
    }

    if(handle->request.payload_length > 0) {
        memcpy(&payload[PID_BYTE_INDEX + handle->request.pid_length],
                handle->request.payload, handle->request.payload_length);
    }

    handle->isotp_send_handle = isotp_send(&handle->isotp_shims,
            handle->request.arbitration_id, payload,
            1 + handle->request.payload_length + handle->request.pid_length,
            NULL);
    if(handle->isotp_send_handle.completed &&
            !handle->isotp_send_handle.success) {
        handle->completed = true;
        handle->success = false;
        if(shims->log != NULL) {
            shims->log("%s", "Diagnostic request not sent");
        }
    } else if(shims->log != NULL) {
        char request_string[128] = {0};
        diagnostic_request_to_string(&handle->request, request_string,
                sizeof(request_string));
        shims->log("Sending diagnostic request: %s", request_string);
    }
}

bool diagnostic_request_sent(DiagnosticRequestHandle* handle) {
    return handle->isotp_send_handle.completed;
}

void start_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequestHandle* handle) {
    handle->success = false;
    handle->completed = false;
    send_diagnostic_request(shims, handle);
    if(!handle->completed) {
        setup_receive_handle(handle);
    }
}

DiagnosticRequestHandle generate_diagnostic_request(DiagnosticShims* shims,
        DiagnosticRequest* request, DiagnosticResponseReceived callback) {
    DiagnosticRequestHandle handle = {
        request: *request,
        callback: callback,
        success: false,
{'fraction_non_alphanumeric': 0.10133961796080378, 'fraction_numerical': 0.010419250806251551, 'mean_word_length': 3.0866700456158136, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '53509', 'n_tokens_mistral': 2723, 'n_tokens_neox': 2578, 'n_words': 426}