#include <acess.h>
#include <modules.h>
#include <udi.h>
+#include "udi_internal.h"
+
+// === IMPORTS ===
+extern udi_init_t pci_init;
+extern char pci_udiprops[];
+extern size_t pci_udiprops_size;
// === PROTOTYPES ===
int UDI_Install(char **Arguments);
int UDI_DetectDriver(void *Base);
int UDI_LoadDriver(void *Base);
+tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size);
+
+tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule);
+tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize);
+void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst);
+
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
tModuleLoader gUDI_Loader = {
int UDI_Install(char **Arguments)
{
Module_RegisterLoader( &gUDI_Loader );
+
+ UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
+
return MODULE_ERR_OK;
}
*/
int UDI_DetectDriver(void *Base)
{
- if( Binary_FindSymbol(Base, "udi_init_info", NULL) == 0) {
+ Uint unused;
+
+ if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) {
+ return 0;
+ }
+ if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) {
+ Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol");
+ return 0;
+ }
+ if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) {
+ Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol");
return 0;
}
{
udi_init_t *info;
char *udiprops = NULL;
- int udiprops_size = 0;
- int i;
- // int j;
-
- ENTER("pBase", Base);
+ char *udiprops_end = 0;
if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
Binary_Unload(Base);
- LEAVE('i', 0);
return 0;
}
- if( Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops) == 0 ) {
- Log_Warning("UDI", "_udiprops is not defined, this is usually bad");
+ Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops);
+ Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end);
+ Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
+
+ UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
+
+ #if 0
+ // Create initial driver instance
+ tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
+
+ // Bind to parent
+ // TODO: This will move to udi_enumerate_ack handling
+ for( int i = 0; i < driver_module->nParents; i ++ )
+ {
+ tUDI_BindOps *parent = &driver_module->Parents[i];
+ udi_channel_t channel = UDI_CreateChannel_Blank( UDI_int_GetMetaLang(inst, parent->meta_idx) );
+
+ UDI_BindChannel(channel,true, inst, parent->ops_idx, parent->region_idx);
+ //UDI_BindChannel(channel,false, parent_inst, parent_chld->ops_idx, parent_chld->region_idx);
+
+ udi_cb_t *bind_cb = udi_cb_alloc_internal(inst, parent->bind_cb_idx, channel);
+ if( !bind_cb ) {
+ Log_Warning("UDI", "Bind CB index is invalid");
+ continue ;
+ }
+
+ udi_channel_event_cb_t ev_cb;
+ int n_handles = driver_module->InitInfo->primary_init_info->per_parent_paths;
+ udi_buf_path_t handles[n_handles];
+ memset(&ev_cb, 0, sizeof(ev_cb));
+ ev_cb.gcb.channel = channel;
+ ev_cb.event = UDI_CHANNEL_BOUND;
+ ev_cb.params.parent_bound.bind_cb = bind_cb;
+ ev_cb.params.parent_bound.parent_ID = i+1;
+ ev_cb.params.parent_bound.path_handles = handles;
+
+ for( int i = 0; i < n_handles; i ++ ) {
+ //handles[i] = udi_buf_path_alloc_internal(inst);
+ handles[i] = 0;
+ }
+
+ udi_channel_event_ind(&ev_cb);
+ }
+
+ // Send enumeraton request
+ #endif
+
+ return 0;
+}
+
+static udi_index_t _get_token_idx(const char *str, const char **outstr)
+{
+ char *end;
+ int ret = strtol(str, &end, 10);
+ if( ret < 0 || ret > 255 ) {
+ Log_Notice("UDI", "Value '%.*s' out of range for udi_index_t",
+ end-str, str);
+ *outstr = NULL;
+ return 0;
+ }
+ if( *end && !isspace(*end) ) {
+ Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
+ end-str, str, *end);
+ *outstr = NULL;
+ return 0;
}
- else {
- Uint udiprops_end = 0;
- int i, j, nLines;
- char **udipropsptrs;
+ while( *end && isspace(*end) )
+ end ++;
+
+ *outstr = end;
+ return ret;
+}
+static udi_ubit16_t _get_token_uint16(const char *str, const char **outstr)
+{
+ char *end;
+ unsigned long ret = strtoul(str, &end, 10);
+ if( ret > 0xFFFF ) {
+ Log_Notice("UDI", "Value '%.*s' out of range for udi_ubit16_t",
+ end-str, str);
+ *outstr = NULL;
+ return 0;
+ }
+ if( *end && !isspace(*end) ) {
+ Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
+ end-str, str, *end);
+ *outstr = NULL;
+ return 0;
+ }
+ while( *end && isspace(*end) )
+ end ++;
+
+ *outstr = end;
+ return ret;
+}
+static udi_ubit32_t _get_token_uint32(const char *str, const char **outstr)
+{
+ char *end;
+ udi_ubit32_t ret = strtoul(str, &end, 0);
+ if( *end && !isspace(*end) ) {
+ Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
+ end-str, str, *end);
+ *outstr = NULL;
+ return 0;
+ }
+ while( *end && isspace(*end) )
+ end ++;
+
+ *outstr = end;
+ return ret;
+}
+static int _get_token_sym(const char *str, const char **outstr, ...)
+{
+ va_list args;
+ va_start(args, outstr);
+ const char *sym;
+ for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
+ {
+ size_t len = strlen(sym);
+ if( memcmp(str, sym, len) != 0 )
+ continue ;
+ if( str[len] && !isspace(str[len]) )
+ continue ;
- if( Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end) == 0)
- Log_Warning("UDI", "_udiprops_end is not defined");
- Log_Debug("UDI", "udiprops_end = %p", udiprops_end);
- udiprops_size = udiprops_end - (Uint)udiprops;
- Log_Debug("UDI", "udiprops = %p, udiprops_size = 0x%x", udiprops, udiprops_size);
+ // Found it!
+ return idx;
+ }
+ va_end(args);
+
+ const char *end = str;
+ while( !isspace(*end) )
+ end ++;
+ Log_Notice("UDI", "Unknown token '%.*s'",
+ end-str, str);
+
+ *outstr = NULL;
+ return -1;
+}
+
+
+tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size)
+{
+ //UDI_int_DumpInitInfo(info);
+
+ // TODO: Multiple modules?
+ tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,);
+ driver_module->InitInfo = info;
+
+ // - Parse udiprops
+ {
+ const char **udipropsptrs;
- Debug_HexDump("UDI_LoadDriver", udiprops, udiprops_size);
- nLines = 1;
- for( i = 0; i < udiprops_size; i++ )
+ int nLines = 1;
+ for( int i = 0; i < udiprops_size; i++ )
{
if( udiprops[i] == '\0' )
nLines ++;
Log_Debug("UDI", "nLines = %i", nLines);
- udipropsptrs = malloc( sizeof(char*)*nLines );
- udipropsptrs[0] = udiprops;
- j = 0;
- for( i = 0; i < udiprops_size; i++ )
+ udipropsptrs = NEW(const char*,*nLines);
+ int line = 0;
+ udipropsptrs[line++] = udiprops;
+ for( int i = 0; i < udiprops_size; i++ )
{
if( udiprops[i] == '\0' ) {
- //Log_Debug("UDI", "udipropsptrs[%i] = '%s'", j, udipropsptrs[j]);
- udipropsptrs[j++] = &udiprops[i+1];
+ udipropsptrs[line++] = &udiprops[i+1];
+ }
+ }
+ if(udipropsptrs[line-1] == &udiprops[udiprops_size])
+ nLines --;
+
+ for( int i = 0; i < nLines; i ++ )
+ {
+ }
+
+ // Parse out:
+ // 'message' into driver_module->Messages
+ // 'region' into driver_module->RegionTypes
+ // 'module' into driver_module->ModuleName
+
+ int nLocales = 1;
+ int nRegionTypes = 0;
+ for( int i = 0; i < nLines; i ++ )
+ {
+ const char *str = udipropsptrs[i];
+ if( strncmp("module ", str, 7) == 0 ) {
+ driver_module->ModuleName = str + 7;
+ }
+ else if( strncmp("meta ", str, 5) == 0 ) {
+ driver_module->nMetaLangs ++;
+ }
+ else if( strncmp("message ", str, 8) == 0 ) {
+ driver_module->nMessages ++;
+ }
+ else if( strncmp("locale ", str, 7) == 0 ) {
+ nLocales ++;
+ }
+ else if( strncmp("region ", str, 7) == 0 ) {
+ nRegionTypes ++;
+ }
+ else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
+ driver_module->nParents ++;
}
}
- Log_Debug("UDI", "udipropsptrs[%i] = '%s'", j, udipropsptrs[j]);
- Log_Debug("UDI", "udiprops = \"%s\"", udiprops);
+
+ // Allocate structures
+ driver_module->Messages = NEW(tUDI_PropMessage, * driver_module->nMessages);
+ driver_module->nRegionTypes = nRegionTypes;
+ driver_module->RegionTypes = NEW(tUDI_PropRegion, * driver_module->nRegionTypes);
+ driver_module->MetaLangs = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
+ driver_module->Parents = NEW(tUDI_BindOps, * driver_module->nParents);
+
+ // Populate
+ int cur_locale = 0;
+ int msg_index = 0;
+ int ml_index = 0;
+ int parent_index = 0;
+ int next_unpop_region = 1;
+ for( int i = 0; i < nLines; i ++ )
+ {
+ const char *str = udipropsptrs[i];
+ if( strncmp("module ", str, 7) == 0 ) {
+ driver_module->ModuleName = str + 7;
+ }
+ else if( strncmp("meta ", str, 5) == 0 ) {
+ tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
+ ml->meta_idx = _get_token_idx(str+5, &str);
+ if( !str ) continue;
+ ml->interface_name = str;
+ }
+ else if( strncmp("message ", str, 8) == 0 ) {
+ tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
+ msg->locale = cur_locale;
+ msg->index = _get_token_uint16(str+8, &str);
+ if( !str ) continue ;
+ msg->string = str;
+
+ //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
+ }
+ else if( strncmp("locale ", str, 7) == 0 ) {
+ // TODO: Set locale
+ cur_locale = 1;
+ }
+ else if( strncmp("region ", str, 7) == 0 ) {
+ udi_index_t rgn_idx = _get_token_idx(str+7, &str);
+ if( !str ) continue ;
+ // Search for region index (just in case internal_bind_ops appears earlier)
+ tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
+ if( rgn_idx > 0 )
+ {
+ rgn ++;
+ for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
+ if( rgn->RegionIdx == rgn_idx )
+ break;
+ }
+ if(i == next_unpop_region) {
+ if( next_unpop_region == nRegionTypes ) {
+ // TODO: warning if reigon types overflow
+ continue ;
+ }
+ next_unpop_region ++;
+ rgn->RegionIdx = rgn_idx;
+ }
+ }
+ // Parse attributes
+ while( *str )
+ {
+ int sym = _get_token_sym(str, &str,
+ "type", "binding", "priority", "latency", "overrun_time", NULL
+ );
+ if( !str ) break ;
+ switch(sym)
+ {
+ case 0: // type
+ rgn->Type = _get_token_sym(str, &str, "normal", "fp", NULL);
+ break;
+ case 1: // binding
+ rgn->Binding = _get_token_sym(str, &str, "static", "dynamic", NULL);
+ break;
+ case 2: // priority
+ rgn->Priority = _get_token_sym(str, &str,
+ "med", "lo", "hi", NULL);
+ break;
+ case 3: // latency
+ rgn->Latency = _get_token_sym(str, &str,
+ "non_overrunable", "powerfail_warning", "overrunable",
+ "retryable", "non_critical", NULL);
+ break;
+ case 4: // overrun_time
+ rgn->OverrunTime = _get_token_uint32(str, &str);
+ break;
+ }
+ if( !str ) break ;
+ }
+ }
+ else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
+ tUDI_BindOps *bind = &driver_module->Parents[parent_index++];
+ bind->meta_idx = _get_token_idx(str+16, &str);
+ if( !str ) continue ;
+ bind->region_idx = _get_token_idx(str, &str);
+ if( !str ) continue ;
+ bind->ops_idx = _get_token_idx(str, &str);
+ if( !str ) continue ;
+ bind->bind_cb_idx = _get_token_idx(str, &str);
+ if( *str ) {
+ // Expected EOL, didn't get it :(
+ }
+ Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
+ bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
+ }
+ else if( strncmp("internal_bind_ops ", str, 18) == 0 ) {
+ // Get region using index
+ udi_index_t meta = _get_token_idx(str+18, &str);
+ if( !str ) continue ;
+ udi_index_t rgn_idx = _get_token_idx(str, &str);
+ if( !str ) continue ;
+
+ // Search for region index (just in case the relevant 'region' comes after)
+ tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
+ if( rgn_idx > 0 )
+ {
+ rgn ++;
+ for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
+ if( rgn->RegionIdx == rgn_idx )
+ break;
+ }
+ if(i == next_unpop_region) {
+ if( next_unpop_region == nRegionTypes ) {
+ // TODO: warning if reigon types overflow
+ continue ;
+ }
+ next_unpop_region ++;
+ rgn->RegionIdx = rgn_idx;
+ }
+ }
+
+ // Set properties
+ rgn->BindMeta = meta;
+
+ rgn->PriBindOps = _get_token_idx(str, &str);
+ if( !str ) continue ;
+ rgn->SecBindOps = _get_token_idx(str, &str);
+ if( !str ) continue ;
+ rgn->BindCb = _get_token_idx(str, &str);
+ if( !str ) continue ;
+ if( *str ) {
+ // TODO: Please sir, I want an EOL
+ }
+ }
+ else {
+ Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
+ }
+ }
+
+ // Sort message list
+ // TODO: Sort message list
}
+
+ int nSecondaryRgns = 0;
+ for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
+ nSecondaryRgns ++;
+ driver_module->nRegions = 1+nSecondaryRgns;
+
+ // Check for orphan drivers, and create an instance of them when loaded
+ if( driver_module->nParents == 0 )
+ {
+ tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
+ // Enumerate so any pre-loaded drivers are detected
+ UDI_int_BeginEnumeration(inst);
+ }
+ else
+ {
+ // Send rescan requests to all loaded instances that support a parent metalang
+ }
+
+ return driver_module;
+}
+
+void UDI_int_DumpInitInfo(udi_init_t *info)
+{
Log("primary_init_info = %p = {", info->primary_init_info);
{
Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
}
Log("}");
- Log("secondary_init_list = %p", info->secondary_init_list);
- Log("ops_init_list = %p", info->ops_init_list);
+ Log("secondary_init_list = %p {", info->secondary_init_list);
+ for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
+ {
+ Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
+ info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
+ }
+ Log("}");
+ Log("ops_init_list = %p {", info->ops_init_list);
+ for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
+ {
+ Log(" [%i] = {", i);
+ Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
+ Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
+ Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
+ Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
+ Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector);
+// Log(" .op_flags = %p", info->ops_init_list[i].op_flags);
+ Log(" }");
+ }
+ Log("}");
+ Log("cb_init_list = %p {", info->cb_init_list);
+ for( int i = 0; info->cb_init_list[i].cb_idx; i++ )
+ {
+ udi_cb_init_t *ent = &info->cb_init_list[i];
+ Log(" [%i] = {", i);
+ Log(" .cbidx = %i", ent->cb_idx);
+ Log(" .meta_idx = %i", ent->meta_idx);
+ Log(" .meta_cb_num = %i", ent->meta_cb_num);
+ Log(" .scratch_requirement = 0x%x", ent->scratch_requirement);
+ Log(" .inline_size = 0x%x", ent->inline_size);
+ Log(" .inline_layout = %p", ent->inline_layout);
+ Log(" }");
+ }
+}
+
+tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule)
+{
+ tUDI_DriverInstance *inst = NEW_wA(tUDI_DriverInstance, Regions, DriverModule->nRegions);
+ udi_primary_init_t *pri_init = DriverModule->InitInfo->primary_init_info;
+ inst->Module = DriverModule;
+ inst->Regions[0] = UDI_InitRegion(inst, 0, 0, pri_init->rdata_size);
+ udi_secondary_init_t *sec_init = DriverModule->InitInfo->secondary_init_list;
+ if( sec_init )
+ {
+ for( int i = 0; sec_init[i].region_idx; i ++ )
+ {
+ inst->Regions[1+i] = UDI_InitRegion(inst, i,
+ sec_init[i].region_idx, sec_init[i].rdata_size);
+ }
+ }
+
+ inst->ManagementChannel = UDI_CreateChannel_Blank(&cMetaLang_Management);
+ UDI_BindChannel_Raw(inst->ManagementChannel, true,
+ 0, inst->Regions[0]->InitContext, pri_init->mgmt_ops);
+// UDI_BindChannel_Raw(inst->ManagementChannel, false,
+// 1, inst, &cUDI_ManagementMetaagent_Ops); // TODO: ops list for management
+
+ for( int i = 0; i < DriverModule->nRegions; i ++ )
+ Log("Rgn %i: %p", i, inst->Regions[i]);
+
+ // Send usage indication
+ char scratch[pri_init->mgmt_scratch_requirement];
+ {
+ udi_usage_cb_t ucb;
+ memset(&ucb, 0, sizeof(ucb));
+ ucb.gcb.scratch = scratch;
+ ucb.gcb.channel = inst->ManagementChannel;
+ udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
+ // TODO: Ensure that udi_usage_res is called
+ }
- for( i = 0; info->ops_init_list[i].ops_idx; i++ )
+ for( int i = 1; i < DriverModule->nRegions; i ++ )
{
- Log("info->ops_init_list[%i] = {", i);
- Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
- Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
- Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
- Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
- Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector);
-// Log(" .op_flags = %p", info->ops_init_list[i].op_flags);
- Log("}");
+ //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank(
+ // TODO: Bind secondaries to primary
}
- return 0;
+ return inst;
+}
+
+tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize)
+{
+// ASSERTCR( RDataSize, <=, UDI_MIN_ALLOC_LIMIT, NULL );
+ ASSERTCR( RDataSize, >=, sizeof(udi_init_context_t), NULL );
+ tUDI_DriverRegion *rgn = NEW(tUDI_DriverRegion,+RDataSize);
+ rgn->InitContext = (void*)(rgn+1);
+ rgn->InitContext->region_idx = Type;
+// rgn->InitContext->limits
+ return rgn;
+}
+
+void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst)
+{
+ udi_primary_init_t *pri_init = Inst->Module->InitInfo->primary_init_info;
+ char scratch[pri_init->mgmt_scratch_requirement];
+ udi_enumerate_cb_t ecb;
+ memset(&ecb, 0, sizeof(ecb));
+ ecb.gcb.scratch = scratch;
+ ecb.gcb.channel = Inst->ManagementChannel;
+ ecb.child_data = malloc( pri_init->child_data_size);
+ ecb.attr_list = NEW(udi_instance_attr_list_t, *pri_init->enumeration_attr_list_length);
+ ecb.attr_valid_length = 0;
+ udi_enumerate_req(&ecb, UDI_ENUMERATE_START);
}
+
+// TODO: Move this stuff out
+udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
+{
+ udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list;
+ while( ops->ops_idx && ops->ops_idx != index )
+ ops ++;
+ if(ops->ops_idx == 0)
+ return NULL;
+ return ops;
+}
+
+tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index)
+{
+ if( index == 0 )
+ return &cMetaLang_Management;
+ for( int i = 0; i < Inst->Module->nMetaLangs; i ++ )
+ {
+ if( Inst->Module->MetaLangs[i].meta_idx == index )
+ return Inst->Module->MetaLangs[i].metalang;
+ }
+ return NULL;
+}
+
+void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
+{
+ udi_cb_init_t *cb_init = NULL;
+ for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
+ {
+ if( cb_init->cb_idx == bind_cb_idx )
+ {
+ udi_cb_t *ret = NEW(udi_cb_t, + cb_init->inline_size + cb_init->scratch_requirement);
+ ret->channel = channel;
+ return ret;
+ }
+ }
+ Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
+ bind_cb_idx, Inst->Module->ModuleName);
+ return NULL;
+
+}
+