int CAN_device_init(uint8_t channel, uint32_t baud)
{
	pr_info("Initializing CAN");
	pr_info_int(channel);
	pr_info_int_msg(" with baud rate ", baud);

	if (!initQueues()) {
		pr_info("CAN init queues failed\r\n");
		return 0;
	}

	switch (channel) {
	case 0:
		CAN_device_init_1(baud);
		break;
	case 1:
		CAN_device_init_2(baud);
		break;
	default:
		pr_info("CAN init device failed\r\n");
		return 0;
	}

	/* Clear out all filter values except 0.  It accepts all. */
	CAN_device_set_filter(channel, 0, 1, 0, 0, true);
	for (size_t i = 1; i < CAN_FILTER_COUNT; ++i)
		CAN_device_set_filter(channel, i, 0, 0, 0, false);

	pr_info("CAN init success!\r\n");
	return 1;
}
static void lapstats_setup(const GpsSnapshot *gps_snapshot)
{
    /*
     * I am not a fan of this method.  Really this track config stuff should
     * get moved over into its own file with its own separate testing.  It
     * should generate an event when a track is detected so that we can listen
     * and act accordingly.  For now it stays here.
     */
    const LoggerConfig *config = getWorkingLoggerConfig();
    const GeoPoint *gp = &gps_snapshot->sample.point;

    const Track *track = NULL;
    const TrackConfig *trackConfig = &(config->TrackConfigs);
    if (trackConfig->auto_detect) {
        track = auto_configure_track(NULL, gp);
        if (track)
            pr_info_int_msg("track: detected track ",
                            track->trackId);
    } else {
        track = &trackConfig->track;
        pr_info("track: using fixed config");
    }

    const float gc_radius = degrees_to_meters(config->TrackConfigs.radius);
    lapstats_setup_internals(track, gc_radius, trackConfig->auto_detect);
}
enum script_add_result flashScriptPage(const unsigned int page,
                                       const char *data,
                                       const enum script_add_mode mode)
{
        if (page >= MAX_SCRIPT_PAGES) {
                pr_error("lua: invalid script index\r\n");
                return SCRIPT_ADD_RESULT_FAIL;
        }

        switch (mode) {
        case SCRIPT_ADD_MODE_IN_PROGRESS:
        case SCRIPT_ADD_MODE_COMPLETE:
                /* Valid cases.  Carry on */
                break;
        default:
                pr_error_int_msg("lua: Unknown script_add_mode: ", mode);
                return SCRIPT_ADD_RESULT_FAIL;
        }

        static ScriptConfig *g_scriptBuffer;
        if (NULL == g_scriptBuffer) {
                terminate_lua();

                pr_debug("lua: Allocating new script buffer\r\n");
                g_scriptBuffer =
                        (ScriptConfig *) portMalloc(sizeof(ScriptConfig));
                memcpy((void *)g_scriptBuffer, (void *)&g_scriptConfig,
                       sizeof(ScriptConfig));
        }

        if (NULL == g_scriptBuffer) {
                pr_error("lua: Failed to allocate memory for script "
                         "buffer.\r\n");
                return SCRIPT_ADD_RESULT_FAIL;
        }

        char *pageToAdd = g_scriptBuffer->script + page * SCRIPT_PAGE_SIZE;
        strncpy(pageToAdd, data, SCRIPT_PAGE_SIZE);

        if (SCRIPT_ADD_MODE_IN_PROGRESS == mode)
                return SCRIPT_ADD_RESULT_OK;

        pr_info("lua: Completed updating LUA. Flashing... ");
        const int rc = memory_flash_region((void*) &g_scriptConfig,
                                           (void*) g_scriptBuffer,
                                           sizeof(ScriptConfig));
        portFree(g_scriptBuffer);
        g_scriptBuffer = NULL;

        if (0 != rc) {
                pr_info_int_msg("failed with code ", rc);
                return SCRIPT_ADD_RESULT_FAIL;
        }

        pr_info("win!\r\n");
        initialize_lua();
        return SCRIPT_ADD_RESULT_OK;
}
enum track_add_result add_track(const Track *track, const size_t index,
                                const enum track_add_mode mode)
{
        if (index >= MAX_TRACK_COUNT) {
                pr_error("tracks: Invalid track index\r\n");
                return TRACK_ADD_RESULT_FAIL;
        }

        switch (mode) {
        case TRACK_ADD_MODE_IN_PROGRESS:
        case TRACK_ADD_MODE_COMPLETE:
                /* Valid cases.  Carry on */
                break;
        default:
                pr_error_int_msg("tracks: Unknown track_add_mode: ", mode);
                return TRACK_ADD_RESULT_FAIL;
        }

        static Tracks *g_tracksBuffer;
        if (NULL == g_tracksBuffer) {

#if LUA_SUPPORT
                lua_task_stop();
#endif /* LUA_SUPPORT */

                pr_debug("tracks: Allocating new tracks buffer\r\n");
                g_tracksBuffer = (Tracks *) portMalloc(sizeof(Tracks));
                memcpy(g_tracksBuffer, (void*) &g_tracks, sizeof(Tracks));
        }

        if (NULL == g_tracksBuffer) {
                pr_error("tracks: Failed to allocate memory for track buffer.\r\n");
                return TRACK_ADD_RESULT_FAIL;
        }

        Track *trackToAdd = g_tracksBuffer->tracks + index;
        memcpy(trackToAdd, track, sizeof(Track));
        g_tracksBuffer->count = index + 1;

        /* If we made it here and are still in progress, then we are done */
        if (TRACK_ADD_MODE_IN_PROGRESS == mode)
                return TRACK_ADD_RESULT_OK;

        /* If here, time to flash and tidy up */
        pr_info("tracks: Completed updating tracks. Flashing... ");
        const int rc = flash_tracks(g_tracksBuffer, sizeof(Tracks));
        portFree(g_tracksBuffer);
        g_tracksBuffer = NULL;

        if (0 != rc) {
                pr_info_int_msg("failed with code ", rc);
                return TRACK_ADD_RESULT_FAIL;
        }

        pr_info("win!\r\n");

#if LUA_SUPPORT
        lua_task_start();
#endif /* LUA_SUPPORT */

        return TRACK_ADD_RESULT_OK;
}