#include <udi_internal.h>
#include <udi_internal_ma.h> // for cUDI_MgmtCbInitList
+typedef struct sUDI_CBHeader
+{
+ tUDI_MetaLang *Metalang;
+ udi_index_t MetaCBNum;
+ udi_cb_t cb;
+} tUDI_CBHeader;
+
// === CODE ===
+tUDI_MetaLang *UDI_int_GetCbType(udi_cb_t *cb, udi_index_t *meta_cb_num)
+{
+ tUDI_CBHeader *hdr = (void*)cb - offsetof(tUDI_CBHeader, cb);
+ if(meta_cb_num)
+ *meta_cb_num = hdr->MetaCBNum;
+ return hdr->Metalang;
+}
+
+udi_cb_t *udi_cb_alloc_internal_v(tUDI_MetaLang *Meta, udi_index_t MetaCBNum,
+ size_t inline_size, size_t scratch_size, udi_channel_t channel)
+{
+ ASSERTC(MetaCBNum, <, Meta->nCbTypes);
+ size_t base = Meta->CbTypes[MetaCBNum].Size;
+ ASSERTC(base, >=, sizeof(udi_cb_t));
+ base -= sizeof(udi_cb_t);
+ LOG("+ %i + %i + %i", base, inline_size, scratch_size);
+ tUDI_CBHeader *cbhdr = NEW(tUDI_CBHeader, + base + inline_size + scratch_size);
+ cbhdr->Metalang = Meta;
+ cbhdr->MetaCBNum = MetaCBNum;
+ udi_cb_t *ret = &cbhdr->cb;
+ ret->channel = channel;
+ ret->scratch = (void*)(ret + 1) + base + inline_size;
+ return ret;
+}
void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
{
const udi_cb_init_t *cb_init;
LOG("Inst=%p, bind_cb_idx=%i, channel=%p", Inst, bind_cb_idx, channel);
- if(Inst) {
- ASSERT(Inst->Module);
- ASSERT(Inst->Module->InitInfo);
- ASSERT(Inst->Module->InitInfo->cb_init_list);
- }
- cb_init = Inst ? Inst->Module->InitInfo->cb_init_list : cUDI_MgmtCbInitList;
- for( ; cb_init->cb_idx; cb_init ++ )
+ ASSERT(Inst);
+ ASSERT(Inst->Module);
+ ASSERT(Inst->Module->InitInfo);
+ ASSERT(Inst->Module->InitInfo->cb_init_list);
+
+ for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
{
if( cb_init->cb_idx == bind_cb_idx )
{
// TODO: Get base size using meta/cbnum
- tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst, cb_init->meta_idx);
+ tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst->Module, cb_init->meta_idx);
if( !metalang ) {
Log_Warning("UDI", "Metalang referenced in %s CB %i is invalid (%i)",
Inst->Module->ModuleName, bind_cb_idx, cb_init->meta_idx);
return NULL;
}
+ return udi_cb_alloc_internal_v(metalang, cb_init->meta_cb_num,
+ cb_init->inline_size, cb_init->scratch_requirement, channel);
+ #if 0
ASSERTC(cb_init->meta_cb_num, <, metalang->nCbTypes);
size_t base = metalang->CbTypes[cb_init->meta_cb_num].Size;
ASSERTC(base, >=, sizeof(udi_cb_t));
udi_cb_t *ret = NEW(udi_cb_t, + base
+ cb_init->inline_size + cb_init->scratch_requirement);
ret->channel = channel;
+ ret->scratch = (void*)ret + sizeof(udi_cb_t) + base + cb_init->inline_size;
return ret;
+ #endif
}
}
Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
void udi_cb_free(udi_cb_t *cb)
{
- UNIMPLEMENTED();
+ tUDI_CBHeader *hdr = (void*)cb - offsetof(tUDI_CBHeader, cb);
+ // TODO: Ensure that cb is inactive
+ free(hdr);
}
void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb)