Example #1
0
/*
 * This function just returns the work item. If there is data inside that you want
 * you have to unmarshal it after you receive the work item.
 */
AJ_Status AJ_WSL_WMI_WaitForWorkItem(uint32_t socket, uint8_t command, wsl_work_item** item, uint32_t timeout)
{
    AJ_Status status;
    AJ_Time timer;
    AJ_InitTimer(&timer);
//    AJ_AlwaysPrintf(("WaitForWorkItem: %x\n", command));
    //wsl_work_item* item;
    status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout);
    timeout -= AJ_GetElapsedTime(&timer, TRUE);
    if ((status == AJ_OK) && item && *item) {
        if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_INTERUPT)) {
            // We don't care about the interrupted signal for any calls using this function
            AJ_WSL_WMI_FreeWorkItem((*item));
            status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout);
        }
        if ((status == AJ_OK) && ((*item)->itemType == command)) {
            AJ_InfoPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received work item %s\n", WSL_WorkItemText(command)));
            return AJ_OK;
        } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DISCONNECT)) {
            AJ_InfoPrintf(("Got disconnect while waiting for %s\n", WSL_WorkItemText(command)));
            // Clean up the network queues
            int i;
            for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) {
                wsl_work_item* clear;
                AJ_WSL_SOCKET_CONTEXT[i].valid = FALSE;
                // Removed any stashed data
                AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[i].stashedRxList, 1);
                // Reallocate a new stash
                AJ_WSL_SOCKET_CONTEXT[i].stashedRxList = AJ_BufListCreate();
                // Reset the queue, any work items are now invalid since the socket was closed
                while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, &clear, 0) == AJ_OK) {
                    AJ_WSL_WMI_FreeWorkItem(clear);
                }
                while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &clear, 0) == AJ_OK) {
                    AJ_WSL_WMI_FreeWorkItem(clear);
                }
                AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue);
                AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue);
            }
            AJ_WSL_WMI_FreeWorkItem((*item));
            return AJ_ERR_LINK_DEAD;
        } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DATA_RX)) {
            // If we got data we want to save it and not throw it away, its still not what we
            // wanted so we can free the work item as it wont be needed at a higher level
            AJ_InfoPrintf(("Got data while waiting for %s\n", WSL_WorkItemText(command)));
            if ((*item)->node->length) {
                AJ_BufNode* new_node = AJ_BufNodeCreateAndTakeOwnership((*item)->node);
                AJ_BufListPushTail(AJ_WSL_SOCKET_CONTEXT[socket].stashedRxList, new_node);
                AJ_WSL_WMI_FreeWorkItem((*item));
                return AJ_ERR_NULL;
            }
        } else {
            AJ_WarnPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received incorrect work item %s, wanted %s\n", WSL_WorkItemText((*item)->itemType), WSL_WorkItemText(command)));
            // Wrong work item, but return NULL because we can free the item internally
            AJ_WSL_WMI_FreeWorkItem((*item));
            return AJ_ERR_NULL;
        }
    }
    return AJ_ERR_NULL;
}
Example #2
0
/*
 * Print relevant information about the drivers current state. This should
 * only be called upon a crash as it will corrupt the current state information
 * after it has been called.
 */
void AJ_WSL_PrintDriverTraceback(void)
{
    int i;
    dbgWSL_WMI = 5;
    AJ_AlwaysPrintf(("Driver state: "));
    if (AJ_WSL_HTC_Global.started) {
        AJ_AlwaysPrintf(("Started\n"));
    } else {
        AJ_AlwaysPrintf(("Not Started\n"));
    }
    for (i = 0; i < 4; i++) {
        AJ_AlwaysPrintf(("Endpoint %d credits: %d\n", i, AJ_WSL_HTC_Global.endpoints[i].txCredits));
    }
    for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) {
        uint32_t stashSz = 0;
        AJ_BufNode* stashNode = AJ_WSL_SOCKET_CONTEXT[i].stashedRxList->head;
        int j = 0;
        wsl_work_item* item;
        AJ_AlwaysPrintf(("------ SOCKET CONTEXT %d -----\n", i));
        AJ_AlwaysPrintf(("\tSocket Handle: 0x%x\n", AJ_WSL_SOCKET_CONTEXT[i].targetHandle));
        if (AJ_WSL_SOCKET_CONTEXT[i].domain == WSL_AF_INET) {
            AJ_AlwaysPrintf(("Domain: AF_INET\n"));
        } else {
            AJ_AlwaysPrintf(("Domain: AF_INET6\n"));
        }
        if (AJ_WSL_SOCKET_CONTEXT[i].type == WSL_SOCK_STREAM) {
            AJ_AlwaysPrintf(("Type: SOCK_STREAM\n"));
        } else {
            AJ_AlwaysPrintf(("Type: SOCK_DGRAM\n"));
        }
        if (AJ_WSL_SOCKET_CONTEXT[i].valid) {
            while (stashNode != NULL) {
                stashSz += stashNode->length;
                stashNode = stashNode->next;
            }
            AJ_AlwaysPrintf(("\tStash size = %u\n", stashSz));
            AJ_AlwaysPrintf(("\tworkRxQueue:\n"));
            while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, &item, 0) == AJ_OK) {
                AJ_AlwaysPrintf(("\t\tQueue Index %i:", j));
                AJ_AlwaysPrintf(("\tItem Type: %s\n", WSL_WorkItemText(item->itemType)));
                j++;
            }
            if (j == 0) {
                AJ_AlwaysPrintf(("\tworkRxQueue empty\n"));
            }
            j = 0;
            AJ_AlwaysPrintf(("\tworkTxQueue:\n"));
            while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &item, 0) == AJ_OK) {
                AJ_AlwaysPrintf(("\t\tQueue Index %i:", j));
                AJ_AlwaysPrintf(("\tItem Type: %s\n", WSL_WorkItemText(item->itemType)));
                j++;
            }
            if (j == 0) {
                AJ_AlwaysPrintf(("\tworkTxQueue empty\n"));
            }
        } else {
            AJ_AlwaysPrintf(("Socket context %d: Not valid or not open\n", i));
        }
        AJ_AlwaysPrintf(("\n"));
    }
}
Example #3
0
/*
 * Poll over a socket until there is data ready or till a timeout
 *
 * Returns -2 on timeout
 *         -1 on interrupted
 *          1 on success
 *          0 on close
 *
 */
int16_t AJ_WSL_NET_socket_select(AJ_WSL_SOCKNUM sock, uint32_t timeout)
{
    AJ_Time timer;
    wsl_work_item* peek;
    AJ_Status status;
    int16_t ret = 0;
    // Check if the socket is valid
    if (sock >= AJ_WSL_SOCKET_MAX) {
        // tried to get data from an invalid socket, return an error
        return ret;
    }
    if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) {
        // tried to get data from an invalid socket, return the data read from the stash
        AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1);
        AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate();
        //flush the queue
        return ret;
    }
    AJ_InitTimer(&timer);
    // There are 5 conditions that we need to check for
    // 1. If we got an interrupted work item
    // 2. If there is data in the RX stash
    // 3. If there is a RX work item in the queue
    // 4. If there is a socket close work item in the queue
    // 5. If the timeout has expired
    while (1) {
        status = AJ_QueuePeek(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek);
        //AJ_AlwaysPrintf(("Item type = %u\n", peek->itemType));
        if ((status == AJ_OK) && (peek->itemType == WSL_NET_INTERUPT)) {
            // Pull the interrupted item off because we dont need it anymore
            AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0);
            AJ_WSL_WMI_FreeWorkItem(peek);
            ret = -1;
            break;
        } else if (AJ_BufListLengthOnWire(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList) > 0) {
            ret = 1;
            break;
        } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_DATA_RX)) {
            ret = 1;
            break;
        } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_CLOSE ||
                                         peek->itemType == WSL_NET_DISCONNECT ||
                                         peek->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_SOCK_CLOSE))) {
            // Pull the close work item off the queue
            AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0);
            // Socket was closed so tear down the connections
            AJ_WSL_SOCKET_CONTEXT[sock].valid = FALSE;
            // Removed any stashed data
            AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1);
            // Reallocate a new stash
            AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate();
            // Reset the queue, any work items are now invalid since the socket was closed
            AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue);
            AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workTxQueue);
            AJ_WSL_WMI_FreeWorkItem(peek);
            ret = 0;
            break;
        } else if (AJ_GetElapsedTime(&timer, TRUE) >= timeout) {
            ret = -2;
            break;
        }
    }
    return ret;
}
Example #4
0
/*
 *  create the WMI request to bind a socket on the target device to an address and port
 */
int16_t AJ_WSL_NET_socket_recv(AJ_WSL_SOCKNUM sock, uint8_t* buffer, uint32_t sizeBuffer, uint32_t timeout)
{
//    AJ_InfoPrintf(("AJ_WSL_NET_socket_recv()\n"));
    int16_t ret = -1;
    uint32_t rx = sizeBuffer;
    uint32_t stash = 0;
    // read from stash first.
    uint16_t stashLength;

    if (sock >= AJ_WSL_SOCKET_MAX) {
        // tried to get data from an invalid socket, return an error
        return ret;
    }
    if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) {
        // tried to get data from an invalid socket, return the data read from the stash
        AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1);
        AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate();
        //flush the queue
        AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue);
        return ret;
    }

    if (AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList) {
        stashLength = AJ_BufListLengthOnWire(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList);
        if (stashLength != 0) {
            stash = min(rx, stashLength);
            AJ_BufListCopyBytes(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, stash, buffer);
            AJ_BufListPullBytes(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, stash); // shift left-overs toward the start.
            ret = stash;
            sizeBuffer -= stash;
        }
    }


    // wait until there is data
    if (sizeBuffer) {
        wsl_work_item* item = NULL;
        AJ_Status status;

        // the stash was depleted and you want more data
        if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) {
            // tried to get data from an invalid socket, return the data read from the stash
            return ret;
        }


        status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, timeout);
        if (item) {
            if (item->itemType == WSL_NET_INTERUPT) {
                // At this point we dont care about the interrupted signal but we are expecting a RX packet
                // so we need to pull the next item off the queue
                AJ_WSL_WMI_FreeWorkItem(item);
                status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, timeout);
            }
            if ((status == AJ_OK) && (item->itemType == WSL_NET_DISCONNECT)) {
                AJ_InfoPrintf(("Disconnect received\n"));
                // Clean up the network queues
                int i;
                for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) {
                    AJ_WSL_SOCKET_CONTEXT[i].valid = FALSE;
                    // Removed any stashed data
                    AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[i].stashedRxList, 1);
                    // Reallocate a new stash
                    AJ_WSL_SOCKET_CONTEXT[i].stashedRxList = AJ_BufListCreate();
                    // Reset the queue, any work items are now invalid since the socket was closed
                    AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue);
                    AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue);
                }
                ret = -1;
            } else if ((status == AJ_OK) && (item->itemType == WSL_NET_CLOSE || item->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_SOCK_CLOSE))) {
                // Pull the close work item off the queue
                AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, 0);
                // Socket was closed so tear down the connections
                AJ_WSL_SOCKET_CONTEXT[sock].valid = FALSE;
                // Removed any stashed data
                AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1);
                // Reallocate a new stash
                AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate();
                // Reset the queue, any work items are now invalid since the socket was closed
                AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue);
                AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workTxQueue);
                ret = -1;
            } else if ((status == AJ_OK) && (item->itemType == WSL_NET_DATA_RX)) {

                //AJ_InfoPrintf(("=====DATA RX ITEM RECEIVED=====\n"));
                //AJ_DumpBytes("DATA RX ITEM", item->node->buffer, item->size);
                rx = min(sizeBuffer, item->size);
                memcpy(buffer + stash, item->node->buffer, rx);
                AJ_BufNodePullBytes(item->node, rx);
                // check node: if not empty assign to stash.
                if (item->node->length) {
                    AJ_BufListPushTail(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, item->node);
                    item->node = NULL;
                }
                ret = rx + stash;
            } else {
                AJ_InfoPrintf(("AJ_WSL_NET_socket_recv(): BAD WORK ITEM RECEIVED\n"));
            }
            AJ_WSL_WMI_FreeWorkItem(item);
        } else {
            ret = 0;
            AJ_InfoPrintf(("socket_recv timed out\n"));
        }
    }

    return ret;
}
Example #5
0
void AJ_WSL_MBoxListenAndProcessTask(void* parameters)
{
    g_b_spi_interrupt_data_ready = FALSE;
    AJ_WSL_SPI_InitializeSPIController();

    set_SPI_registers();
    write_BOOT_PARAM();

    g_b_spi_interrupt_data_ready = FALSE;

    // loop and process all of the responses
    while (1) {
        AJ_Status status;

        AJ_WSL_HTC_ProcessInterruptCause();

        uint8_t i;
        for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) {
            do {
                wsl_work_item* item = NULL;

                // peek at the queue, then make sure we have enough credits
                // if we have enough, pull and send the workitem to the MBOX
                // otherwise, move to the next socket and then eventually out of this loop.
                // Credits would be available again once AJ_WSL_HTC_ProcessInterruptCause has
                // read any credit-adjustment trailers
                status = AJ_QueuePeek(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &item);
                if ((status != AJ_OK) || (AJ_WSL_HTC_Global.endpoints[item->endpoint].txCredits < 1)) {
                    break;
                }

                // pull a work item off of a socket queue and send it
                AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &item, 0);
                if (!item) {
                    break;
                } else {
                    //AJ_AlwaysPrintf(("AJ_WSL_MBoxListenAndProcessTask: %x\n", item->itemType));
                    AJ_WSL_WriteBufListToMBox(0, item->endpoint, AJ_BufListLengthOnWire(item->list), item->list);

                    /*
                     * if this item is sending data, create a workitem indicating completion
                     * this special check is needed because there is no socket send command in WMI,
                     * otherwise we could handle it in AJ_WSL_WMI_ProcessWMIEvent
                     */
                    if (item->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_NET_DATA_TX)) {
                        wsl_work_item** ppWork;
                        wsl_work_item* sockWork;
                        sockWork = (wsl_work_item*)AJ_WSL_Malloc(sizeof(wsl_work_item));
                        memset(sockWork, 0, sizeof(wsl_work_item));
                        sockWork->itemType = item->itemType;
                        sockWork->endpoint = item->endpoint;
                        ppWork = &sockWork;
                        AJ_QueuePush(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, ppWork, AJ_TIMER_FOREVER);
                    }
                    AJ_WSL_WMI_FreeWorkItem(item);
                }
            } while (1);
        }
        if (!g_b_spi_interrupt_data_ready) {
            AJ_YieldCurrentTask();
        }
        g_b_spi_interrupt_data_ready = FALSE; // reset the state of the interrupt signal
    }
}