#include <ubixos/message.h>
#include <lib/kmalloc.h>
static int inited = 0;
#define __MESSAGE_CONNECTION_COUNT 4
static const int connectionCount = __MESSAGE_CONNECTION_COUNT;
static int messageCount = 0;
static connection_t * connections;
static void messageInit()
{
int i;
if (inited)
return;
connections = (connection_t *) kmalloc(connectionCount * sizeof(connection_t), -1);
for (i = 0; i < connectionCount; i++)
{
kmemset(&connections[i], '\0', sizeof(connection_t));
waitQueueInit(&connections[i].message_queue, 0);
waitQueueInit(&connections[i].old_queue, 0);
}
inited = 1;
}
int connectionCreate(char * cname, uInt32 * cid, uInt8 flags)
{
int i;
if (!inited)
messageInit();
for (i = 0; i < connectionCount; i++)
if (connections[i].used == 0)
break;
if (connections[i].used != 0)
return -1;
connections[i].used = 1;
kstrncpy(connections[i].unique_string, cname, 256);
connections[i].owning_pid = _current->id;
*cid = i;
return 0;
}
int kstrncmp(const char * a, const char * b, int c)
{
int i = 0;
while (i < c)
{
if ((a[i] != b[i]) || (a[i] == '\0') || (b[i] == '\0'))
return a[i] - b[i];
i++;
}
return 0;
}
int connectionOpen(char * cname, uInt32 * cid)
{
int i;
if (!inited)
messageInit();
for (i = 0; i < connectionCount; i++)
if (connections[i].used == 1)
if (0 == kstrncmp(connections[i].unique_string, cname, 256))
break;
if (connections[i].used == 0)
return -1;
if (0 != kstrncmp(connections[i].unique_string, cname, 256))
return -1;
*cid = i;
return 0;
}
int messageRecv(uInt32 cid, uInt32 * sender, uInt32 * cmd, uInt32 * size, uInt8 * data)
{
message_t * temp = NULL;
int notUsed;
if (!inited)
return -1;
if (cid >= connectionCount)
return -1;
//if (connections[cid].used == 0);
// return -1;
if (connections[cid].owning_pid != _current->id)
return -1;
do
{
temp = waitQueueRemove(&connections[cid].message_queue, ¬Used);
if (temp == NULL)
{
setTaskStatus_task(_current, MSGWAIT);
schedule();
}
}
while(temp == NULL);
kmemcpy(data, temp->data, temp->size);
*cmd = temp->cmd;
*size = temp->size;
*sender = temp->send_taskId;
waitQueueInsert(&connections[cid].old_queue, temp, temp->id);
return temp->id;
}
int messageSend(uInt32 cid, uInt32 * cmd, uInt32 * size, uInt8 * data)
{
volatile message_t * temp;
kTask_t * task;
if (!inited)
return -1;
if (cid >= connectionCount)
return -1;
if (connections[cid].used == 0)
return -1;
temp = (message_t *) kmalloc(sizeof(message_t), -1);
temp->cmd = *cmd;
temp->size = *size;
kmemcpy((void *) temp->data, (void *) data, *size);
temp->send_taskId = _current->id;
temp->id = messageCount;
messageCount++;
temp->flags = MSG_SEND;
waitQueueInsert(&connections[cid].message_queue, (void *) temp, temp->id);
task = getTask(connections[cid].owning_pid);
if (task != NULL)
{
if (task->status == MSGWAIT)
setTaskStatus_task(task, READY);
}
while((temp->flags & MSG_REPLY) != MSG_REPLY)
{
setTaskStatus_task(_current, MSGREPLY);
schedule();
}
*cmd = temp->cmd;
*size= temp->size;
kmemcpy((void *) data, (void *) temp->data, *size);
kfree((void *)temp);
return 0;
}
int messageReply(uInt32 cid, uInt32 mid, uInt32 cmd, uInt32 size, uInt8 * data)
{
message_t * temp = NULL;
if (!inited)
return -1;
if (cid >= connectionCount)
return -1;
if (connections[cid].used == 0)
return -1;
temp = waitQueueFind(&connections[cid].old_queue, mid);
if (temp == NULL)
return -1;
temp->flags |= MSG_REPLY;
temp->size = size;
temp->cmd = cmd;
kmemcpy(temp->data, data, cmd);
setTaskStatus(temp->send_taskId, READY);
return 0;
}