/**
 * @brief Initialize the provided mutex
 *
 * Call this function to initialize the mutex
 *
 * @param IoT_Mutex_t - pointer to the mutex to be initialized
 * @return IoT_Error_t - error code indicating result of operation
 */
IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) {
	if (os_mutex_create(&pMutex->lock, "aws-mutex", OS_MUTEX_INHERIT)
	    != WM_SUCCESS) {
		return MUTEX_LOCK_ERROR;
	}
	return AWS_SUCCESS;
}
Exemple #2
0
Gui::Gui(GenesisContext *context, ResourceBundle *resource_bundle) :
    _running(true),
    _focus_window(nullptr),
    _utility_window(create_utility_window()),
    _resource_bundle(resource_bundle),
    _spritesheet(this, "spritesheet"),
    img_entry_dir(_spritesheet.get_image_info("font-awesome/folder.png")),
    img_entry_dir_open(_spritesheet.get_image_info("font-awesome/folder-open.png")),
    img_entry_file(_spritesheet.get_image_info("font-awesome/file.png")),
    img_plus(_spritesheet.get_image_info("font-awesome/plus-square.png")),
    img_minus(_spritesheet.get_image_info("font-awesome/minus-square.png")),
    img_microphone(_spritesheet.get_image_info("font-awesome/microphone.png")),
    img_volume_up(_spritesheet.get_image_info("font-awesome/volume-up.png")),
    img_check(_spritesheet.get_image_info("font-awesome/check.png")),
    img_caret_right(_spritesheet.get_image_info("font-awesome/caret-right.png")),
    img_caret_down(_spritesheet.get_image_info("font-awesome/caret-down.png")),
    img_arrow_up(_spritesheet.get_image_info("font-awesome/arrow-up.png")),
    img_arrow_down(_spritesheet.get_image_info("font-awesome/arrow-down.png")),
    img_arrow_left(_spritesheet.get_image_info("font-awesome/arrow-left.png")),
    img_arrow_right(_spritesheet.get_image_info("font-awesome/arrow-right.png")),
    img_music(_spritesheet.get_image_info("font-awesome/music.png")),
    img_plug(_spritesheet.get_image_info("font-awesome/plug.png")),
    img_exclamation_circle(_spritesheet.get_image_info("font-awesome/exclamation-circle.png")),
    img_null(_spritesheet.get_image_info("img/null.png")),
    img_play_head(_spritesheet.get_image_info("img/play_head.png")),
    _genesis_context(context),
    dragging(false),
    drag_data(nullptr),
    drag_window(nullptr)
{

    ft_ok(FT_Init_FreeType(&_ft_library));
    _resource_bundle->get_file_buffer("font.ttf", _default_font_buffer);
    ft_ok(FT_New_Memory_Face(_ft_library, (FT_Byte*)_default_font_buffer.raw(),
                _default_font_buffer.length(), 0, &_default_font_face));

    cursor_default = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
    cursor_ibeam = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
    cursor_hresize = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
    cursor_vresize = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);

    genesis_set_audio_device_callback(_genesis_context, audio_device_callback, this);
    genesis_set_midi_device_callback(_genesis_context, midi_device_callback, this);

    genesis_set_sound_backend_disconnect_callback(_genesis_context, sound_backend_disconnect_callback, this);

    genesis_flush_events(_genesis_context);
    genesis_refresh_midi_devices(_genesis_context);

    gui_mutex = ok_mem(os_mutex_create());

    os_mutex_lock(gui_mutex);
}
Exemple #3
0
 LockedQueue() {
     _start = 0;
     _end = 0;
     _length = 0;
     _capacity = 0;
     _items = NULL;
     _shutdown = false;
     if (!(_mutex = os_mutex_create()))
         mutex_err = GenesisErrorNoMem;
     if (!(_cond = os_cond_create()))
         cond_err = GenesisErrorNoMem;
 }
Exemple #4
0
int seminfo_init(void)
{
	int ret;
	ret = os_mutex_create(&sem_mutex, "sem-mutex",
			OS_MUTEX_INHERIT);
	if (ret == -WM_FAIL) {
		wmprintf("[sem-dbg] Failed to create sem-mutex\r\n");
		return -WM_FAIL;
	}
	if (cli_register_commands
	(&cli[0], sizeof(cli) / sizeof(struct cli_command)))
		return 1;
	return 0;
}
Exemple #5
0
/*********************************************************//**
Initializes global event and OS 'slow' mutex lists. */
UNIV_INTERN
void
os_sync_init(void)
/*==============*/
{
	UT_LIST_INIT(os_event_list);
	UT_LIST_INIT(os_mutex_list);

	os_sync_mutex = NULL;
	os_sync_mutex_inited = FALSE;

	os_sync_mutex = os_mutex_create(NULL);

	os_sync_mutex_inited = TRUE;
}
sync_array_t*
sync_array_create(
/*==============*/
				/* out, own: created wait array */
	ulint	n_cells,	/* in: number of cells in the array
				to create */
	ulint	protection)	/* in: either SYNC_ARRAY_OS_MUTEX or
				SYNC_ARRAY_MUTEX: determines the type
				of mutex protecting the data structure */
{
	sync_array_t*	arr;
	sync_cell_t*	cell_array;
	sync_cell_t*	cell;
	ulint		i;

	ut_a(n_cells > 0);

	/* Allocate memory for the data structures */
	arr = ut_malloc(sizeof(sync_array_t));

	cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells);

	arr->n_cells = n_cells;
	arr->n_reserved = 0;
	arr->array = cell_array;
	arr->protection = protection;
	arr->sg_count = 0;
	arr->res_count = 0;

	/* Then create the mutex to protect the wait array complex */
	if (protection == SYNC_ARRAY_OS_MUTEX) {
		arr->os_mutex = os_mutex_create(NULL);
	} else if (protection == SYNC_ARRAY_MUTEX) {
		mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
	} else {
		ut_error;
	}

	for (i = 0; i < n_cells; i++) {
		cell = sync_array_get_nth_cell(arr, i);
	cell->wait_object = NULL;
		cell->waiting = FALSE;
		cell->signal_count = 0;
	}

	return(arr);
}
Exemple #7
0
/*******************************************************************//**
Creates a synchronization wait array. It is protected by a mutex
which is automatically reserved when the functions operating on it
are called.
@return	own: created wait array */
UNIV_INTERN
sync_array_t*
sync_array_create(
/*==============*/
	ulint	n_cells,	/*!< in: number of cells in the array
				to create */
	ulint	protection)	/*!< in: either SYNC_ARRAY_OS_MUTEX or
				SYNC_ARRAY_MUTEX: determines the type
				of mutex protecting the data structure */
{
	ulint		sz;
	sync_array_t*	arr;

	ut_a(n_cells > 0);

	/* Allocate memory for the data structures */
	arr = ut_malloc(sizeof(sync_array_t));
	memset(arr, 0x0, sizeof(*arr));

	sz = sizeof(sync_cell_t) * n_cells;
	arr->array = ut_malloc(sz);
	memset(arr->array, 0x0, sz);

	arr->n_cells = n_cells;
	arr->protection = protection;

	/* Then create the mutex to protect the wait array complex */
	if (protection == SYNC_ARRAY_OS_MUTEX) {
		arr->os_mutex = os_mutex_create();
	} else if (protection == SYNC_ARRAY_MUTEX) {
		mutex_create(syn_arr_mutex_key,
			     &arr->mutex, SYNC_NO_ORDER_CHECK);
	} else {
		ut_error;
	}

	return(arr);
}
Exemple #8
0
int lcd_drv_init(I2C_ID_Type id)
{
	int ret;
	MDEV_lcd.name = MDEV_NAME_lcd;

	if (mdev_get_handle(MDEV_NAME_lcd) != NULL)
		return WM_SUCCESS;

	pinmux_drv_init();
	gpio_drv_init();
	i2c_drv_init(id);

	ret = os_mutex_create(&lcd_mutex, "lcd", OS_MUTEX_INHERIT);
	if (ret == -WM_FAIL) {
		lcd_e("Failed to create mutex");
		return -WM_FAIL;
	}

	mdev_register(&MDEV_lcd);
	MDEV_lcd.private_data = (uint32_t) id;
	init_lcd();

	return WM_SUCCESS;
}
/* Basic Sensor IO initialization to be done here

	This function will be called only once during sensor registration
 */
int co2_sensor_init(struct sensor_info *curevent)
{
    int ret;

    if (co2_sinit_f)
        return 0;
    co2_sinit_f = 1;

    /* using IO_48 and IO_49 for Sensor Communication
    	Please NOTE:
    	This need relevent change in board file
     */
    uart_drv_init(UART2_ID, UART_8BIT);

    ret = os_mutex_create(&co2uart_mutex, "uart-co2",
                          OS_MUTEX_INHERIT);

    if (ret != WM_SUCCESS)
        return -WM_FAIL;

    uart2_dev = uart_drv_open(UART2_ID, CO2_UART_BAUD);

    return 0;
}
int ssp_drv_init(SSP_ID_Type id)
{
	int ret;

	if (mdev_get_handle(mdev_ssp_name[id]) != NULL)
		return WM_SUCCESS;

	ret = os_mutex_create(&ssp_mutex[id], "ssp-write",
			      OS_MUTEX_INHERIT);
	if (ret == -WM_FAIL) {
		SSP_LOG("Failed to create mutex");
		return -WM_FAIL;
	}

	/* Initialize the SSP port's mdev structure */
	ssp_drv_mdev_init(id);

	/* Register the SSP device driver for this port */
	mdev_register(&mdev_ssp[id]);

	fill_cb_array();

	return WM_SUCCESS;
}
/**
 *  @brief C main entry function
 *  @param argc     number of arguments
 *  @param argv     A pointer to arguments array
 *  @return         WPS_STATUS_SUCCESS--success, otherwise--fail
 */
int wps_start(struct wps_config *wps_conf)
{
	int ret;
	WPS_DATA *wps_s = (WPS_DATA *) &wps_global;
#ifdef CONFIG_WPA2_ENTP
	WPA_SM *wpa_sm_s = (WPA_SM *) &wpa_sm;
#endif

	if (wps.initialized == true)
		return -WM_FAIL;

	local_wcc = wps_conf;

	memset((void *)&wps, 0, sizeof(wps));
#ifdef CONFIG_P2P
	wps.peer_event_queue_data = wps_peer_event_queue_data;
	wps.event_queue_data = wps_event_queue_data;
#endif
	wps.cmd_queue_data = wps_cmd_queue_data;
	wps.data_queue_data = wps_data_queue_data;
	wps.cb = local_wcc->wps_callback;

#ifdef CONFIG_P2P
	/* WFD data initiliazation */
	memset(&wps_s->wfd_data, 0, sizeof(WFD_DATA));
	wps_s->wfd_data.dev_index = -1;
	wps_s->wfd_data.dev_found = -1;

	ret = os_mutex_create(&wps.p2p_session, "p2p_session",
						OS_MUTEX_INHERIT);
	if (ret != WM_SUCCESS) {
		WPS_LOG("Error: Failed to create "
				"p2p session mutex: %d\r\n", ret);
		goto fail;
	}

	ret =
	    os_queue_create(&wps.event_queue, "wps_event_queue",
			    sizeof(struct wfd_wlan_event),
				&wps.event_queue_data);
	if (ret != WM_SUCCESS) {
		WPS_LOG
		    ("Error: Failed to create wps event queue: %d\r\n", ret);
		goto fail;
	}

	ret =
	    os_queue_create(&wps.peer_event_queue, "wps_peer_event_queue",
			    sizeof(struct wfd_wlan_event),
				&wps.peer_event_queue_data);
	if (ret != WM_SUCCESS) {
		WPS_LOG
		    ("Error: Failed to create wps peer "
				"event queue: %d\r\n", ret);
		goto fail;
	}
	ret = wifi_register_wfd_event_queue(&wps.peer_event_queue);
	if (ret) {
		WPS_LOG("Error: unable to register peer "
				"event queue %d\r\n", ret);
		os_queue_delete(&wps.peer_event_queue);
		goto fail;
	}
#endif

	ret =
	    os_queue_create(&wps.cmd_queue, "wps_cmd_queue",
			    sizeof(struct wps_command **), &wps.cmd_queue_data);
	if (ret != WM_SUCCESS) {
		WPS_LOG("Error: Failed to create wps cmd queue: %d\r\n", ret);
		goto fail;
	}

	ret =
	    os_queue_create(&wps.data_queue, "wps_message_queue",
			    sizeof(struct wps_msg), &wps.data_queue_data);
	if (ret != WM_SUCCESS) {
		WPS_LOG
		    ("Error: Failed to create wps message queue: %d\r\n", ret);
		goto fail;
	}

#ifdef CONFIG_CYASSL
	ctaocrypt_lib_init();
#endif

	wps.initialized = true;

	memset(wps_s->ifname, 0, IFNAMSIZ + 1);

#ifdef CONFIG_P2P
	if (local_wcc->role == WFD_ROLE)
		strncpy(wps_s->ifname, "wfd0", IFNAMSIZ);
	else if (local_wcc->role == WPS_REGISTRAR)
		strncpy(wps_s->ifname, "uap0", IFNAMSIZ);
	else
#endif
		strncpy(wps_s->ifname, "mlan0", IFNAMSIZ);

	gpwps_info_initialized = false;

	ret = wps_private_info_allocate(&gpwps_info);

	wps_printf(DEBUG_INIT, "Initializing interface '%s'", wps_s->ifname);

#ifdef CONFIG_P2P
	if (local_wcc->role == WFD_ROLE) {
		if (auto_go)
			wps_s->bss_type = BSS_TYPE_UAP;
		else
			wps_s->bss_type = BSS_TYPE_STA;
	} else if (local_wcc->role == WPS_REGISTRAR)
		wps_s->bss_type = BSS_TYPE_UAP;
	else
		wps_s->bss_type = BSS_TYPE_STA;

	gpwps_info->discovery_role = WPS_ENROLLEE;
#else
	wps_s->bss_type = BSS_TYPE_STA;
#endif

	/*
	 * 1. Initialize L2 packet interface for receiving EAP packet.
	 * 2. Get L2 MAC address and store to application global structure
	 */
	if (wps_loop_init(wps_s) != 0) {
		wps_printf(MSG_ERROR,
			   "ERROR - Fail to initialize layer 2 socket !\n");
		wps_stop();
		goto fail;
	}
#ifdef CONFIG_WPA2_ENTP
	memset(wpa_sm_s, 0, sizeof(WPA_SM));

	wpa_sm_s->pairwise_cipher = WPA_CIPHER_CCMP;
	wpa_sm_s->group_cipher = WPA_CIPHER_CCMP;
	wpa_sm_s->proto = WPA_PROTO_RSN;
	wpa_sm_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
	wpa_sm_s->renew_snonce = 1;
	memcpy(wpa_sm_s->own_addr, wps_s->l2->my_mac_addr, ETH_ALEN); 
#endif

#ifdef CONFIG_P2P
	ret = os_thread_create(&wps_main_thread, "p2p", wps_main, 0,
			       &wps_stack, OS_PRIO_3);
	if (ret != WM_SUCCESS) {
		WPS_LOG("Error: Failed to create p2p thread: %d\r\n", ret);
		goto fail;
	}

	if (!auto_go) {
		ret = os_thread_create(&p2p_scan_thread, "p2p_scan",
				wps_peer_event_receive, 0,
				&p2p_scan_stack, OS_PRIO_3);

		if (ret != WM_SUCCESS) {
			WPS_LOG("Error: Failed to create p2p_scan"
				" thread: %d\r\n", ret);
			goto fail;
		}
	}
#else
	ret = os_thread_create(&wps_main_thread, "wps", wps_main, 0,
			       &wps_stack, OS_PRIO_3);
	if (ret != WM_SUCCESS) {
		WPS_LOG("Error: Failed to create wps thread: %d\r\n", ret);
		goto fail;
	}
#endif

	return WM_SUCCESS;

fail:
	if (wps_main_thread)
		os_thread_delete(&wps_main_thread);
	if (wps.cmd_queue)
		os_queue_delete(&wps.cmd_queue);
	if (wps.data_queue)
		os_queue_delete(&wps.data_queue);
#ifdef CONFIG_P2P
	if (wps.p2p_session)
		os_mutex_delete(&wps.p2p_session);
	if (wps.peer_event_queue)
		os_queue_delete(&wps.peer_event_queue);
	if (wps.event_queue)
		os_queue_delete(&wps.event_queue);
#endif

	return -WM_FAIL;
}
Exemple #12
0
int main()
{
    int ret;

    	
	modules_init();//模块的初始化
    
	user_init();
    /* system tag data  */
    store_or_retrive_taged_config();
    
    get_mcu_version_from_psm();

    LOG_DEBUG("rst cause is %x\r\n", boot_reset_cause());

#ifdef MIIO_COMMANDS
    mcmd_enqueue_raw("MIIO_model_req");
    mcmd_enqueue_raw("MIIO_mcu_version_req");
#endif

    ret = os_mutex_create(&network_state_mutex,"network_state",OS_MUTEX_INHERIT);
    if(WM_SUCCESS != ret) {
        LOG_ERROR("create network_state_mutex fail");
        goto main_error;
    }

    register_device_network_state_observer(led_network_state_observer);
    
    /*set wifi calbration data*/
    product_set_wifi_cal_data();

    /* Start the application framework */
    if ((ret = app_framework_start(common_event_handler)) != WM_SUCCESS) {
        LOG_ERROR("Failed to start application framework.\r\n");
#if defined(CONFIG_CPU_MC200)
        if (-WLAN_ERROR_FW_DNLD_FAILED == ret || -WLAN_ERROR_FW_NOT_DETECTED == ret
                || -WLAN_ERROR_FW_NOT_READY == ret) {
            LOG_WARN("Wifi firmware broken, trying to recover.\r\n");
            if (recover_wifi_fw() != WM_SUCCESS) {
                LOG_FATAL("Recovering wifi fw failed!!!\r\n");
            } else {
                LOG_WARN("Recovering wifi fw success.\r\n");
                pm_reboot_soc();
            }
        }
#endif
        appln_critical_error_handler((void *) -WM_FAIL);
    }

    ret = is_factory_mode_enable();
    LOG_DEBUG("factory mode magic is %x\r\n" ,get_factory_mode_enable());
    if (0 == ret) {
        // user mode
        static xTaskHandle task_handle;
        if (app_thread) {
            xTaskCreate(app_thread, (signed char*) "app", 2000, NULL, APPLICATION_PRIORITY,
                    &task_handle);
            xTaskCreate(app_uart_thread, (signed char*) "app_uart", 2000, NULL, APPLICATION_PRIORITY,
                    &task_handle);
            LOG_INFO("App thread and App uart thread started.\r\n");
        }
    } else {
        // factory mode
        static xTaskHandle task_handle;
        if (app_test_thread) {
            xTaskCreate(app_test_thread, (signed char*) "test", 2000, NULL, 2,
                    &task_handle);
            LOG_INFO("Test thread started.\r\n");
        }
    }
    
    // Initialize power management
	hp_pm_init();
    
    //enter main loop, main loop will be used as a worker thread
    main_loop_run();

    //main loop return means error
main_error: 
    pm_reboot_soc(); //error occure on main thread , reboot
	return 1;
}
/***********************************************************
*  Function: gw_cntl_init
*  Input: 
*  Output: 
*  Return: 
***********************************************************/
OPERATE_RET gw_cntl_init(VOID)
{
    OPERATE_RET op_ret;

    op_ret = httpc_aes_init();
    if(OPRT_OK != op_ret) {
        PR_ERR("op_ret:%d",op_ret);
        return op_ret;        
    }

    op_ret = ws_db_init();
    if(OPRT_OK != op_ret) {
        return op_ret;
    }

    memset(&gw_cntl,0,sizeof(gw_cntl));
    memset(&gw_mutex,0,sizeof(gw_mutex));

    // create mutex
    int ret;
    ret = os_mutex_create(&gw_mutex, "gw_mutex", 1);
    if(ret != WM_SUCCESS) {
        return OPRT_CR_MUTEX_ERR;
    }

    // create gw active timer
    ret = os_timer_create(&gw_actv_timer,
				  "gw_actv_timer",
				  os_msec_to_ticks(1000),
				  &gw_actv_timer_cb,
				  NULL,
				  OS_TIMER_PERIODIC,
				  OS_TIMER_NO_ACTIVATE);
	if (ret != WM_SUCCESS) {
		return OPRT_COM_ERROR;
	}

    PROD_IF_REC_S prod_if;    
#if 1
    memset(&prod_if,0,sizeof(prod_if));
    ws_db_get_prod_if(&prod_if);
    if(!prod_if.mac[0] || !prod_if.prod_idx[0]) { // un init
        set_gw_status(UN_INIT);
        return OPRT_OK;
    }
#else
    strcpy(prod_if.mac,"112233445566");
    strcpy(prod_if.prod_idx,"0da02001");
#endif

    op_ret = ws_db_get_gw_actv(&gw_cntl.active);
    if(OPRT_OK != op_ret) {
        memset(&gw_cntl.active,0,sizeof(gw_cntl.active));
        ws_db_set_gw_actv(&gw_cntl.active);
        set_gw_status(UN_ACTIVE);
    }else {
        if(!gw_cntl.active.key[0] || !gw_cntl.active.uid_cnt) { // un active
            if(!gw_cntl.active.token[0]) {
                set_gw_status(UN_ACTIVE);
            }else {
                start_active_gateway();
            }
        }else {
            set_gw_status(STAT_WORK);
        }
    }

    strcpy(gw_cntl.gw.sw_ver,GW_VER);
    #if 0
    strcpy(gw_cntl.gw.name,GW_DEF_NAME);
    #else
    snprintf(gw_cntl.gw.name,sizeof(gw_cntl.gw.name),"%s-%s",GW_DEF_NAME,&prod_if.mac[8]);
    #endif
    snprintf(gw_cntl.gw.id,sizeof(gw_cntl.gw.id),"%s%s",prod_if.prod_idx,prod_if.mac);
    gw_cntl.gw.ability = GW_DEF_ABI;

    // create dev upload timer
    ret = os_timer_create(&dev_ul_timer,
				  "dev_ul_timer",
				  os_msec_to_ticks(600),
				  &dev_ul_timer_cb,
				  NULL,
				  OS_TIMER_PERIODIC,
				  OS_TIMER_NO_ACTIVATE);
	if (ret != WM_SUCCESS) {
		return OPRT_COM_ERROR;
	}

    return OPRT_OK;
}
Exemple #14
0
int create_midi_hardware(GenesisContext *context,
        const char *client_name,
        void (*events_signal)(struct MidiHardware *),
        void (*on_devices_change)(struct MidiHardware *),
        void *userdata,
        struct MidiHardware **out_midi_hardware)
{
    *out_midi_hardware = nullptr;

    struct MidiHardware *midi_hardware = create_zero<MidiHardware>();
    if (!midi_hardware) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }
    midi_hardware->context = context;
    midi_hardware->on_buffer_overrun = default_on_buffer_overrun;
    midi_hardware->events_signal = events_signal;
    midi_hardware->on_devices_change = on_devices_change;
    midi_hardware->userdata = userdata;

    if (!(midi_hardware->mutex = os_mutex_create())) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }

    if (snd_seq_open(&midi_hardware->seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_set_client_name(midi_hardware->seq, client_name) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    snd_seq_client_info_malloc(&midi_hardware->client_info);
    snd_seq_port_info_malloc(&midi_hardware->port_info);

    if (!midi_hardware->client_info || !midi_hardware->port_info) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }

    if (snd_seq_create_simple_port(midi_hardware->seq, "genesis",
                SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
                SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION) < 0)
    {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    int err = midi_hardware_refresh(midi_hardware);
    if (err) {
        destroy_midi_hardware(midi_hardware);
        return err;
    }

    if (!midi_hardware->system_announce_device) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_connect_from(midi_hardware->seq, 0,
                midi_hardware->system_announce_device->client_id,
                midi_hardware->system_announce_device->port_id) < 0)
    {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_get_client_info(midi_hardware->seq, midi_hardware->client_info) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    midi_hardware->client_id = snd_seq_client_info_get_client(midi_hardware->client_info);
    if (snd_seq_connect_from(midi_hardware->seq, 0, midi_hardware->client_id, 0) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if ((err = os_thread_create(midi_thread, midi_hardware, false, &midi_hardware->thread))) {
        destroy_midi_hardware(midi_hardware);
        return err;
    }

    *out_midi_hardware = midi_hardware;
    return 0;
}
int ordered_map_file_open(const char *path, OrderedMapFile **out_omf) {
    *out_omf = nullptr;
    OrderedMapFile *omf = create_zero<OrderedMapFile>();
    if (!omf) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (!(omf->cond = os_cond_create())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (!(omf->mutex = os_mutex_create())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (omf->queue.error()) {
        ordered_map_file_close(omf);
        return omf->queue.error();
    }
    omf->list = create_zero<List<OrderedMapFileEntry *>>();
    if (!omf->list) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }

    omf->map = create_zero<HashMap<ByteBuffer, OrderedMapFileEntry *, ByteBuffer::hash>>();
    if (!omf->map) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }

    omf->running = true;
    int err;
    if ((err = os_thread_create(run_write, omf, false, &omf->write_thread))) {
        ordered_map_file_close(omf);
        return err;
    }

    bool open_for_writing = false;
    omf->file = fopen(path, "rb+");
    if (omf->file) {
        int err = read_header(omf);
        if (err == GenesisErrorEmptyFile) {
            open_for_writing = true;
        } else if (err) {
            ordered_map_file_close(omf);
            return err;
        }
    } else {
        open_for_writing = true;
    }
    if (open_for_writing) {
        omf->file = fopen(path, "wb+");
        if (!omf->file) {
            ordered_map_file_close(omf);
            return GenesisErrorFileAccess;
        }
        int err = write_header(omf);
        if (err) {
            ordered_map_file_close(omf);
            return err;
        }
    }

    // read everything into list
    bool partial_transaction = false;
    omf->write_buffer.resize(TRANSACTION_METADATA_SIZE);
    omf->transaction_offset = UUID_SIZE;
    for (;;) {
        size_t amt_read = fread(omf->write_buffer.raw(), 1, TRANSACTION_METADATA_SIZE, omf->file);
        if (amt_read != TRANSACTION_METADATA_SIZE) {
            // partial transaction. ignore it and we're done.
            if (amt_read > 0)
                partial_transaction = true;
            break;
        }
        uint8_t *transaction_ptr = (uint8_t*)omf->write_buffer.raw();
        int transaction_size = read_uint32be(&transaction_ptr[4]);
        if (transaction_size < TRANSACTION_METADATA_SIZE ||
            transaction_size > MAX_TRANSACTION_SIZE)
        {
            // invalid value
            partial_transaction = true;
            break;
        }

        omf->write_buffer.resize(transaction_size);
        transaction_ptr = (uint8_t*)omf->write_buffer.raw();

        size_t amt_to_read = transaction_size - TRANSACTION_METADATA_SIZE;
        amt_read = fread(&transaction_ptr[TRANSACTION_METADATA_SIZE], 1, amt_to_read, omf->file);
        if (amt_read != amt_to_read) {
            // partial transaction. ignore it and we're done.
            partial_transaction = true;
            break;
        }
        uint32_t computed_crc = crc32(0, &transaction_ptr[4], transaction_size - 4);
        uint32_t crc_from_file = read_uint32be(&transaction_ptr[0]);
        if (computed_crc != crc_from_file) {
            // crc check failed. ignore this transaction and we're done.
            partial_transaction = true;
            break;
        }

        int put_count = read_uint32be(&transaction_ptr[8]);
        int del_count = read_uint32be(&transaction_ptr[12]);

        int offset = TRANSACTION_METADATA_SIZE;
        for (int i = 0; i < put_count; i += 1) {
            int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4;
            int val_size = read_uint32be(&transaction_ptr[offset]); offset += 4;

            OrderedMapFileEntry *entry = create_zero<OrderedMapFileEntry>();
            if (!entry) {
                ordered_map_file_close(omf);
                return GenesisErrorNoMem;
            }

            entry->key = ByteBuffer((char*)&transaction_ptr[offset], key_size); offset += key_size;
            entry->offset = omf->transaction_offset + offset;
            entry->size = val_size;
            offset += val_size;

            auto old_hash_entry = omf->map->maybe_get(entry->key);
            if (old_hash_entry) {
                OrderedMapFileEntry *old_entry = old_hash_entry->value;
                destroy(old_entry, 1);
            }

            omf->map->put(entry->key, entry);
        }
        for (int i = 0; i < del_count; i += 1) {
            int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4;
            ByteBuffer key((char*)&transaction_ptr[offset], key_size); offset += key_size;

            auto hash_entry = omf->map->maybe_get(key);
            if (hash_entry) {
                OrderedMapFileEntry *entry = hash_entry->value;
                omf->map->remove(key);
                destroy(entry, 1);
            }
        }

        omf->transaction_offset += transaction_size;

    }

    if (partial_transaction)
        fprintf(stderr, "Warning: Partial transaction found in project file.\n");

    // transfer map to list and sort
    auto it = omf->map->entry_iterator();
    if (omf->list->ensure_capacity(omf->map->size())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    for (;;) {
        auto *map_entry = it.next();
        if (!map_entry)
            break;

        ok_or_panic(omf->list->append(map_entry->value));
    }
    omf->map->clear();
    destroy_map(omf);

    omf->list->sort<compare_entries>();

    *out_omf = omf;
    return 0;
}