/* ---------------------------------------------------------------------- * initialise host-side OpenMAX IL component service * -------------------------------------------------------------------- */ void vc_vchi_ilcs_init( VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) { int32_t success; SERVICE_CREATION_T parameters = { MAKE_FOURCC("ILCS"), // 4cc service code connections[0], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) 0, // service callback 0 }; // callback parameter memset( &vc_ilcsg, 0, sizeof(VC_ILCS_GLOBALS_T) ); // create thread semaphore for blocking os_semaphore_create( &vc_ilcsg.component_lock, OS_SEMAPHORE_TYPE_SUSPEND ); // create semaphore for protecting wait/xid structures os_semaphore_create( &vc_ilcsg.wait_sem, OS_SEMAPHORE_TYPE_SUSPEND ); // create semaphore for correct ordering of control+bulk pairs os_semaphore_create( &vc_ilcsg.send_sem, OS_SEMAPHORE_TYPE_SUSPEND ); // open 'ILCS' service success = vchi_service_open( initialise_instance, ¶meters, &vc_ilcsg.vchi_handle ); vc_assert( success == 0 ); success = os_thread_start( &vc_ilcsg.thread, vc_ilcs_task, NULL, 4000, "ILCS_HOST" ); vc_assert( success == 0 ); }
void vc_vchi_gencmd_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) { int32_t success; int i; // record the number of connections memset( &gencmd_client, 0, sizeof(GENCMD_SERVICE_T) ); gencmd_client.num_connections = (int) num_connections; success = os_semaphore_create( &gencmd_client.sema, OS_SEMAPHORE_TYPE_SUSPEND ); assert( success == 0 ); success = os_semaphore_create( &gencmd_message_available_semaphore, OS_SEMAPHORE_TYPE_BUSY_WAIT ); assert( success == 0 ); success = os_semaphore_obtain( &gencmd_message_available_semaphore ); assert( success == 0 ); for (i=0; i<gencmd_client.num_connections; i++) { // Create a 'LONG' service on the each of the connections SERVICE_CREATION_T gencmd_parameters = { MAKE_FOURCC("GCMD"), // 4cc service code connections[i], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) &gencmd_callback, // service callback &gencmd_message_available_semaphore, // callback parameter VC_FALSE, // want_unaligned_bulk_rx VC_FALSE, // want_unaligned_bulk_tx VC_FALSE // want_crc }; success = vchi_service_open( initialise_instance, &gencmd_parameters, &gencmd_client.open_handle[i] ); assert( success == 0 ); } }
/*********************************************************** * Name: software_fifo_create * * Arguments: const uint32_t size - size of FIFO (in bytes) * int alignment - required alignment (bytes) * SOFTWARE_FIFO_HANDLE_T *handle - handle to this FIFO * * Description: Allocates space for a FIFO and initialises it * * Returns: 0 if successful, any other value is failure * ***********************************************************/ int32_t software_fifo_create( const uint32_t size, int alignment, SOFTWARE_FIFO_HANDLE_T *handle ) { int32_t success = -1; // check that the alignment is a power of 2 or 0 os_assert((OS_COUNT(alignment) == 1) || (alignment == 0)); // put the alignment into a form we can use (must be power of 2) alignment = alignment ? alignment-1 : 0; // check we have a valid pointer if(handle) { memset(handle,0,sizeof(SOFTWARE_FIFO_HANDLE_T)); // allocate slightly more space than we need so that we can get the required alignment handle->malloc_address = (uint8_t *)os_malloc(size+alignment, OS_ALIGN_DEFAULT, ""); if(handle->malloc_address) { handle->base_address = (uint8_t *)(((uint32_t)handle->malloc_address + alignment) & ~alignment); handle->read_ptr = handle->base_address; handle->write_ptr = handle->base_address; handle->size = size; handle->bytes_read = 0; handle->bytes_written = 0; success = os_semaphore_create(&handle->software_fifo_semaphore,OS_SEMAPHORE_TYPE_SUSPEND); // oops, unable to create the semaphore os_assert(success == 0); } } // oops, looks like you've run out of memory os_assert(success == 0); return(success); }
/* ---------------------------------------------------------------------- * initialise host-side OpenMAX IL component service * -------------------------------------------------------------------- */ void vc_vchi_ilcs_init( VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) { int32_t success; memset( &vc_ilcsg, 0, sizeof(VC_ILCS_GLOBALS_T) ); // sema_init(&vc_ilcsg.msg_prod, 0); sema_init(&vc_ilcsg.msg_cons, 1); sema_init(&vc_ilcsg.omxlog_lock, 1); vc_ilcsg.omxlog_rindex = 0; vc_ilcsg.omxlog_windex = 0; vc_ilcsg.omxlog = vmalloc(VC03_OMXLOG_MAX); memset(vc_ilcsg.omxlog, 0, VC03_OMXLOG_MAX); // create thread semaphore for blocking os_semaphore_create( &vc_ilcsg.component_lock, OS_SEMAPHORE_TYPE_SUSPEND ); os_semaphore_create( &vc_ilcsg.rxmsg_sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_semaphore_obtain( &vc_ilcsg.rxmsg_sem ); // create semaphore for protecting wait/xid structures os_semaphore_create( &vc_ilcsg.wait_sem, OS_SEMAPHORE_TYPE_SUSPEND ); // open 'ILCS' service SERVICE_CREATION_T parameters = { MAKE_FOURCC("ILCS"), // 4cc service code connections[0], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) &vc_ilcs_callback, // service callback &vc_ilcsg.rxmsg_sem }; // callback parameter success = vchi_service_open( initialise_instance, ¶meters, &vc_ilcsg.vchi_handle ); assert( success == 0 ); success = os_thread_start( &vc_ilcsg.thread, vc_ilcs_task, NULL, 4000, "ILCS_HOST" ); assert( success == 0 ); }
void vc_vchi_hostreq_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) { int success, i; // record the number of connections memset( &hostreq_client, 0, sizeof(HOSTREQ_SERVICE_T) ); hostreq_client.num_connections = num_connections; success = os_semaphore_create( &hostreq_client.sema, OS_SEMAPHORE_TYPE_SUSPEND ); assert( success == 0 ); success = os_semaphore_create( &hostreq_client_message_available, OS_SEMAPHORE_TYPE_BUSY_WAIT ); assert( success == 0 ); success = os_semaphore_obtain(&hostreq_client_message_available); assert( success == 0 ); for (i=0; i<hostreq_client.num_connections; i++) { // Create a 'Client' service on the each of the connections SERVICE_CREATION_T hostreq_parameters = { HOSTREQ_NAME, // 4cc service code connections[i], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) &hostreq_client_callback, // service callback &hostreq_client_message_available }; // callback parameter success = vchi_service_open( initialise_instance, &hostreq_parameters, &hostreq_client.client_handle[i] ); assert( success == 0 ); } success = os_thread_start(&hostreq_client_task, &hostreqclient_func, NULL, 2048, "HOSTREQ task"); assert(!success); if(!success) { hostreq_client.initialised = 1; //Send a time across immediately time_t dummytime = 0; //We need to get the real time on a real host success = hostreq_send_command(VC_HOSTREQ_TIME, &dummytime, sizeof(dummytime)); assert( success == 0 ); } }
void miio_app_thread(void* arg) { static bool has_sync_time = false; g_mum = mum_create(); //*****************************button init*******************************/ os_timer_create(&g_reset_prov_timer, "reset-prov-timer", os_msec_to_ticks(4000), reset_prov, NULL, OS_TIMER_ONE_SHOT, OS_TIMER_NO_ACTIVATE); button_frame_work_init(); register_button_callback(0, button_1_press_handle); if (WM_SUCCESS != os_semaphore_create(&btn_pressed_sem, "btn_pressed_sem")) { LOG_ERROR("btn_pressed_sem creation failed\r\n"); } else if (WM_SUCCESS != os_semaphore_get(&btn_pressed_sem, OS_WAIT_FOREVER)) { LOG_ERROR("first get btn_pressed_sem failed.\r\n"); } //******************************button init end*******************************************/ local_timer_init();//add by [email protected] miio_led_on(); LOG_INFO("miio_app_thread while loop start.\r\n"); #ifdef MIIO_COMMANDS_DEBUG while(!ot_api_is_online())api_os_tick_sleep(100); uart_wifi_debug_init(); #endif while (1) { if (WM_SUCCESS == os_semaphore_get(&btn_pressed_sem, OS_NO_WAIT)) { mum_set_property(g_mum,"button_pressed","\"wifi_rst\""); } if(has_sync_time)//only after sync time, we start check timer check_schedule_and_set_timer(); else if(otn_is_online()) has_sync_time = true; os_thread_sleep(os_msec_to_ticks(PERIOD_CHECK_BUTTON)); } local_timer_deinit();//add by [email protected] //*****************************button deinit*******************************/ mum_destroy(&g_mum); os_timer_delete(&g_reset_prov_timer); os_semaphore_delete(&btn_pressed_sem); //******************************button deinit end*******************************************/ }
/*********************************************************** * Name: os_init * * Arguments: void * * Description: Routine to init the local OS stack - called from vchi_init * * Returns: int32_t - success == 0 * ***********************************************************/ int32_t os_init( void ) { int success; vcos_init(); os_cond_init(); os_assert(!vcos_os_inited++); /* should only be called once now */ success = os_semaphore_create(&os_mutex_global, OS_SEMAPHORE_TYPE_SUSPEND); os_assert(success == 0); return success; }
/* ---------------------------------------------------------------------- * allocate space for a new non-wrap fifo, and return pointer to * opaque handle. returns NULL on failure * -------------------------------------------------------------------- */ VCHI_NWFIFO_T * non_wrap_fifo_create( const char *name, const uint32_t size, int alignment, int no_of_slots ) { int32_t success = -1; NON_WRAP_FIFO_HANDLE_T *fifo; // check that the alignment is a power of 2 or 0 #ifndef WIN32 os_assert((OS_COUNT(alignment) == 1) || (alignment == 0)); #endif // put the alignment into a form we can use (must be power of 2) alignment = alignment ? alignment - 1 : 0; // create new non-wrap fifo struct fifo = (NON_WRAP_FIFO_HANDLE_T *)os_malloc( sizeof(NON_WRAP_FIFO_HANDLE_T), OS_ALIGN_DEFAULT, "" ); os_assert( fifo ); if (!fifo) return NULL; memset( fifo, 0, sizeof(NON_WRAP_FIFO_HANDLE_T) ); fifo->name = name; // allocate slightly more space than we need so that we can get the required alignment fifo->malloc_address = (uint8_t *)os_malloc(size+alignment, OS_ALIGN_DEFAULT, ""); if ( fifo->malloc_address ) { fifo->base_address = (uint8_t *)(((size_t)fifo->malloc_address + alignment) & ~alignment); fifo->read_ptr = fifo->base_address; fifo->write_ptr = fifo->base_address; // now allocate the space for the slot_info structures fifo->slot_info = (NON_WRAP_SLOT_T *)os_malloc(no_of_slots*sizeof(NON_WRAP_SLOT_T), OS_ALIGN_DEFAULT, ""); memset( fifo->slot_info, 0, no_of_slots * sizeof(NON_WRAP_SLOT_T) ); fifo->size = size; fifo->num_of_slots = no_of_slots; success = os_semaphore_create( &fifo->sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_assert(success == 0); success = os_cond_create( &fifo->space_available_cond, &fifo->sem ); os_assert(success == 0); } else { os_free(fifo); fifo = NULL; } return (VCHI_NWFIFO_T *)fifo; }
void ThreadCheck() { VCOS_THREAD_T thread; // First create a sync semaphore TEST_OK("os_semaphore_create", os_semaphore_create(&sem1, OS_SEMAPHORE_TYPE_SUSPEND)); // and grab it TEST_OK("os_semaphore_obtain", os_semaphore_obtain(&sem1)); // Start the thread which shuold stall on the semaphore TEST_OK("os_thread_start", os_thread_start( &thread, &ThreadOne, NULL, 1000, "ThreadOne")); // Wait for thread to start for 1000 - should stall on semaphore and not change flag TEST_OK("os_delay", os_delay(1000)); // Check global data is unchanged TEST_OK("Flag = 0", flag); // release semaphore TEST_OK("os_semaphore_release", os_semaphore_release(&sem1)); // Wait for thread to continue for 100 - should be enough for it to set the flag TEST_OK("os_delay", os_delay(100)); // Check global data is changed to non-zero TEST_OK("Flag = 1", (flag == 0)); // Semaphore is currently released, so check the obtained function is correct. TEST_OK("os_semaphore_obtained - 0", os_semaphore_obtained(&sem1)) // now get the sema and test again TEST_OK("os_semaphore_obtain", os_semaphore_obtain(&sem1)); TEST_OK("os_semaphore_obtained - 1", (os_semaphore_obtained(&sem1) == 0)) TEST_OK("os_semaphore_release", os_semaphore_release(&sem1)); }
/*********************************************************** * Name: vchi_control_service_init * * Arguments: VCHI_CONNECTION_T *connections, * const uint32_t num_connections * * Description: Routine to init the control service * * Returns: int32_t - success == 0 * ***********************************************************/ int32_t vchi_control_service_init( VCHI_CONNECTION_T **connections, const uint32_t num_connections, void **state ) { int32_t success = 0; uint32_t count = 0; CONTROL_SERVICE_INFO_T *control_info = (CONTROL_SERVICE_INFO_T *)*state; os_assert(num_connections <= VCHI_MAX_NUM_CONNECTIONS); if (!control_info) { control_info = (CONTROL_SERVICE_INFO_T *)os_malloc( VCHI_MAX_NUM_CONNECTIONS * sizeof(CONTROL_SERVICE_INFO_T), 0, "vchi:control_info" ); memset( control_info, 0,VCHI_MAX_NUM_CONNECTIONS * sizeof(CONTROL_SERVICE_INFO_T) ); for( count = 0; count < num_connections; count++ ) { #ifdef VCHI_COARSE_LOCKING os_semaphore_obtain(&connections[count]->sem); #endif // create and obtain the semaphore used to signal when we have connected success += os_semaphore_create( &control_info[count].connected_semaphore, OS_SEMAPHORE_TYPE_BUSY_WAIT ); os_assert( success == 0 ); // record the connection info control_info[count].connection = connections[count]; // create the server (this is a misnomer as the the CTRL service acts as both client and server success += (connections[count])->api->service_connect((connections[count])->state,MAKE_FOURCC("CTRL"),0,0,VC_TRUE,control_callback,&control_info[count],VC_FALSE,VC_FALSE,VC_FALSE,&control_info[count].open_handle); os_assert(success == 0); #ifdef VCHI_COARSE_LOCKING os_semaphore_release(&connections[count]->sem); #endif } // start timestamps from zero time_offset = 0; time_offset -= vchi_control_get_time(); } else { for ( count = 0; count < num_connections; count++ ) { os_assert(control_info[count].connection == connections[count]); } } // because we can have both ends of a connection running on one processor we need to send down the CONNECTION command after all // the connections have been connected for( count = 0; count < num_connections; count++ ) { #ifdef VCHI_COARSE_LOCKING os_semaphore_obtain(&connections[count]->sem); #endif // record that we have not yet handled an INIT request control_info[count].initialised = VC_FALSE; success = os_semaphore_obtain( &control_info[count].connected_semaphore ); os_assert( success == 0 ); success = vchi_control_queue_connect( &control_info[count], VC_FALSE ); os_assert(success == 0); #ifdef VCHI_COARSE_LOCKING os_semaphore_release(&connections[count]->sem); #endif } // now we must wait for the connections to have their INIT returned for( count = 0; count < num_connections; count++ ) { success = os_semaphore_obtain( &control_info[count].connected_semaphore ); os_assert( success == 0 ); success = os_semaphore_release( &control_info[count].connected_semaphore ); os_assert( success == 0 ); } *state = control_info; return success; }
/* ---------------------------------------------------------------------- * send a string to the host side IL component service. if resp is NULL * then there is no response to this call, so we should not wait for one. * * returns response, written to 'resp' pointer * -------------------------------------------------------------------- */ void vc_ilcs_execute_function( IL_FUNCTION_T func, void *data, int len, void *data2, int len2, void *resp, int resplen ) { VC_ILCS_WAIT_T *wait; int num; // the host MUST receive a response assert( resp ); // need to atomically find free ->wait entry os_semaphore_obtain( &vc_ilcsg.wait_sem ); for (;;) { num = 0; while( num < VC_ILCS_MAX_WAITING && vc_ilcsg.wait[num].resp ) num++; if ( num < VC_ILCS_MAX_WAITING ) break; assert( num < VC_ILCS_MAX_WAITING ); // might be a fatal error if another thread is relying // on this call completing before it can complete // we'll pause until we can carry on and hope that's sufficient. os_semaphore_release( &vc_ilcsg.wait_sem ); os_sleep( 10 ); // 10 msec os_semaphore_obtain( &vc_ilcsg.wait_sem ); } wait = &vc_ilcsg.wait[num]; wait->resp = resp; wait->xid = vc_ilcsg.next_xid++; os_semaphore_create( &wait->sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_semaphore_obtain( &wait->sem ); // at this point, ->wait is exclusively ours () os_semaphore_release( &vc_ilcsg.wait_sem ); // write the command header. vc_ilcs_transmit( func, wait->xid, data, len, data2, len2 ); if ( !os_thread_current(vc_ilcsg.thread) ) { os_semaphore_obtain( &wait->sem ); } else { // we're the vcilcs task, so wait for, and handle, incoming // messages while we're not completed for (;;) { // wait->sem will not be released until we process the response message if ( vc_ilcs_process_message() == 0 ) { // there were no more messages in the fifo; need to wait os_semaphore_obtain( &vc_ilcsg.rxmsg_sem ); continue; } // did the last message release wait->sem ? if ( !os_semaphore_obtained(&wait->sem) ) break; } } // safe to do the following - the assignment of NULL is effectively atomic os_semaphore_destroy( &wait->sem ); wait->resp = NULL; }
/* ---------------------------------------------------------------------- * send a string to the host side IL component service. if resp is NULL * then there is no response to this call, so we should not wait for one. * * returns 0 on successful call made, -1 on failure to send call. * on success, the response is written to 'resp' pointer * -------------------------------------------------------------------- */ int vc_ilcs_execute_function( IL_FUNCTION_T func, void *data, int len, void *data2, int len2, void *bulk, int bulk_len, void *resp ) { VC_ILCS_WAIT_T *wait; int i, num; // the host MUST receive a response vc_assert( resp ); // need to atomically find free ->wait entry os_semaphore_obtain( &vc_ilcsg.wait_sem ); // we try a number of times then give up with an error message // rather than just deadlocking for (i=0; i<VC_ILCS_WAIT_TIMEOUT; i++) { num = 0; while( num < VC_ILCS_MAX_WAITING && vc_ilcsg.wait[num].resp ) num++; if ( num < VC_ILCS_MAX_WAITING || i == VC_ILCS_WAIT_TIMEOUT-1) break; // might be a fatal error if another thread is relying // on this call completing before it can complete // we'll pause until we can carry on and hope that's sufficient. os_semaphore_release( &vc_ilcsg.wait_sem ); os_sleep( 10 ); // 10 msec // if we're the vcilcs thread, then the waiters might need // us to handle their response, so try and clear those now if(os_thread_is_running(&vc_ilcsg.thread)) while(vc_ilcs_process_message(0)); os_logging_message( "%s: wait for sem", __FUNCTION__); os_semaphore_obtain( &vc_ilcsg.wait_sem ); } if(num == VC_ILCS_MAX_WAITING) { // failed to send message. vc_assert(0); os_semaphore_release( &vc_ilcsg.wait_sem ); return -1; } wait = &vc_ilcsg.wait[num]; wait->resp = resp; wait->xid = vc_ilcsg.next_xid++; os_semaphore_create( &wait->sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_semaphore_obtain( &wait->sem ); // at this point, ->wait is exclusively ours () os_semaphore_release( &vc_ilcsg.wait_sem ); if(bulk) os_semaphore_obtain( &vc_ilcsg.send_sem); // write the command header. vc_ilcs_transmit( func, wait->xid, data, len, data2, len2 ); if(bulk) { int result; result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle, // call to VCHI bulk, bulk_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); vc_assert(result == 0); os_semaphore_release( &vc_ilcsg.send_sem); } if ( !os_thread_is_running(&vc_ilcsg.thread) ) { os_semaphore_obtain( &wait->sem ); } else { // we're the vcilcs task, so wait for, and handle, incoming // messages while we're not completed for (;;) { // wait->sem will not be released until we process the response message vc_ilcs_process_message(1); // did the last message release wait->sem ? if ( !os_semaphore_obtained(&wait->sem) ) break; } } // safe to do the following - the assignment of NULL is effectively atomic os_semaphore_destroy( &wait->sem ); wait->resp = NULL; return 0; }
/****************************************************************************** NAME vc_vchi_cec_init SYNOPSIS void vc_vchi_cec_init(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) FUNCTION Initialise the CEC service for use. A negative return value indicates failure (which may mean it has not been started on VideoCore). RETURNS int ******************************************************************************/ VCHPRE_ void VCHPOST_ vc_vchi_cec_init(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) { int32_t success = -1; uint32_t i; // record the number of connections memset( &cecservice_client, 0, sizeof(CECSERVICE_HOST_STATE_T) ); cecservice_client.num_connections = num_connections; success = os_semaphore_create( &cecservice_client.sema, OS_SEMAPHORE_TYPE_SUSPEND ); vcos_assert( success == 0 ); success = os_semaphore_create( &cecservice_message_available_semaphore, OS_SEMAPHORE_TYPE_BUSY_WAIT ); vcos_assert( success == 0 ); success = os_semaphore_obtain( &cecservice_message_available_semaphore ); vcos_assert( success == 0 ); success = os_semaphore_create( &cecservice_notify_available_semaphore, OS_SEMAPHORE_TYPE_SUSPEND ); vcos_assert( success == 0 ); success = os_semaphore_obtain( &cecservice_notify_available_semaphore ); vcos_assert( success == 0 ); cecservice_client.topology = os_malloc(sizeof(VC_CEC_TOPOLOGY_T), 16, "CEC topology"); vcos_assert(cecservice_client.topology); for (i=0; i < cecservice_client.num_connections; i++) { // Create a 'Client' service on the each of the connections SERVICE_CREATION_T cecservice_parameters = { CECSERVICE_CLIENT_NAME, // 4cc service code connections[i], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) &cecservice_client_callback,// service callback &cecservice_message_available_semaphore, // callback parameter VC_FALSE, // want_unaligned_bulk_rx VC_FALSE, // want_unaligned_bulk_tx VC_FALSE, // want_crc }; SERVICE_CREATION_T cecservice_parameters2 = { CECSERVICE_NOTIFY_NAME, // 4cc service code connections[i], // passed in fn ptrs 0, // tx fifo size (unused) 0, // tx fifo size (unused) &cecservice_notify_callback,// service callback &cecservice_notify_available_semaphore, // callback parameter VC_FALSE, // want_unaligned_bulk_rx VC_FALSE, // want_unaligned_bulk_tx VC_FALSE, // want_crc }; //Create the client to normal CEC service success = vchi_service_open( initialise_instance, &cecservice_parameters, &cecservice_client.client_handle[i] ); vcos_assert( success == 0 ); //Create the client to the async CEC service (any CEC related notifications) success = vchi_service_open( initialise_instance, &cecservice_parameters2, &cecservice_client.notify_handle[i] ); vcos_assert( success == 0 ); } //Create the notifier task success = os_thread_start(&cecservice_notify_task, cecservice_notify_func, &cecservice_client, 2048, "CEC Notify"); vcos_assert( success == 0 ); cecservice_client.initialised = 1; }