/* * 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; }
static void run_buflist_external(const struct test_case* test) { uint8_t externA[10]; uint8_t externB[10]; /* * verify the buffer list management */ AJ_BufList* list1 = AJ_BufListCreate(); AJ_BufNode* pNode1 = AJ_BufListCreateNodeExternalBuffer((uint8_t*)&externA, sizeof(externA)); AJ_BufNode* pNode2 = AJ_BufListCreateNodeExternalBuffer((uint8_t*)&externB, sizeof(externB)); AJ_AlwaysPrintf(("\n\n**************\nTEST: %s\n\n", __FUNCTION__)); memset(pNode1->buffer, 0x1, pNode1->length); memset(pNode2->buffer, 0x2, pNode2->length); AJ_BufListPushHead(list1, pNode1); AJ_BufListPushTail(list1, pNode2); AJ_BufNodeIterate(AJ_BufListNodePrint, list1, NULL); AJ_BufNodeIterate(AJ_BufListNodePrintDump, list1, NULL); AJ_BufListFree(list1, 1); }
void AJ_WSL_WMI_FreeWorkItem(wsl_work_item* item) { if (item) { AJ_BufListFree(item->list, TRUE); AJ_BufListFreeNodeAndBuffer(item->node, NULL); AJ_WSL_Free(item); } }
/* * 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; }
/* * 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; }
AJ_EXPORT AJ_Status AJ_WSL_NET_connect(const char* SSID, const char* passphrase, WSL_NET_AUTH_MODE auth, WSL_NET_CRYPTO_TYPE crypto, uint8_t softAP) { AJ_Status status; wsl_scan_list* list; list = (wsl_scan_list*)AJ_WSL_GetScanList(); WSL_ClearScanList(list); AJ_WSL_NET_SetPowerMode(2); uint8_t bss_mac[6]; // Open auth does not require you to explicitly set the BSSID so this secondary scan is not needed if (!softAP) { if (auth != WSL_NET_AUTH_NONE) { // Do a scan of just the SSID you want AJ_WSL_SetProbedSSID(SSID, 1); { AJ_BufList* start_scan; uint8_t found = 0; int i; AJ_WSL_NET_set_scan_params(); while (!found) { wsl_work_item* item; AJ_InfoPrintf(("AJ_WSL_NET_scan(): START_SCAN\n")); start_scan = AJ_BufListCreate(); AJ_WSL_SetProbedSSID(SSID, 1); AJ_WSL_NET_set_scan_params(); AJ_WSL_NET_BSS_FILTER(6); WSL_MarshalPacket(start_scan, WSL_START_SCAN, 0, 0, 0, 0, 0, 0, 0, 0); WMI_MarshalHeader(start_scan, 1, 1); AJ_WSL_WMI_PadPayload(start_scan); //AJ_BufListPrintDumpContinuous(start_scan); AJ_WSL_WMI_QueueWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_SCAN), AJ_WSL_HTC_DATA_ENDPOINT1, start_scan); status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_SCAN), &item); AJ_WSL_WMI_FreeWorkItem(item); // Get the new list (just of the SSID provided in the connect command) AJ_WSL_NET_scan_stop(); list = (wsl_scan_list*)AJ_WSL_GetScanList(); if (list->size == 0) { AJ_AlwaysPrintf(("Could not find access point %s\n", SSID)); WSL_ClearScanList(list); AJ_Sleep(AJ_WSL_CONNECT_WAIT); continue; } WSL_PrintScanSorted(); // Find the SSID you want to connect to in the second scan list for (i = 0; i < list->size; i++) { if (0 == strcmp(list->list[i].ssid, SSID)) { memcpy(&bss_mac, list->list[i].bssid, 6); found = 1; break; } } WSL_ClearScanList(list); } } } } { AJ_BufList* connect; AJ_BufList* connectOut; static const uint8_t zero_mac[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t connect_mac[6]; wsl_work_item* item = NULL; uint8_t found = 0; connect = AJ_BufListCreate(); /* Three different ways connect can be called. * 1. SoftAP: The devices mac is fetched and used * 2. Using Auth: The SSID's mac is found and used * 3. Open auth: A zero'ed mac is used */ if (softAP) { WSL_MarshalPacket(connect, WSL_SET_SOFT_AP, 0, 0x04, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, getDeviceMac(), 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else if ((auth != WSL_NET_AUTH_NONE) && (crypto != WSL_NET_CRYPTO_WEP)) { WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &bss_mac, 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else { // if the auth mode is open, use zero_mac, and set flags to zero WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &zero_mac, 0x0000, 0x0000); WMI_MarshalHeader(connect, 1, 1); } AJ_InfoPrintf(("AJ_WSL_NET_connect(): CONNECT\n")); AJ_WSL_WMI_PadPayload(connect); //AJ_BufListPrintDumpContinuous(connect); connectOut = AJ_BufListCreateCopy(connect); AJ_WSL_WMI_QueueWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), AJ_WSL_HTC_DATA_ENDPOINT1, connectOut); if (softAP) { AJ_AlwaysPrintf(("Waiting for a connection to the softAP %s\n", SSID)); memcpy(&connect_mac, (uint8_t*)getDeviceMac(), sizeof(connect_mac)); while (WSL_MacsAreEqual((uint8_t*)&connect_mac, (uint8_t*)getDeviceMac()) == TRUE) { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item); if (item) { if (item->itemType == WSL_NET_CONNECT) { AJ_InfoPrintf(("AJ_WSL_ip6config(): WORK ITEM RECEIVED\n")); uint16_t WMIEvent; uint32_t toss; uint16_t channel; WMI_Unmarshal(item->node->buffer, "quqM", &WMIEvent, &toss, &channel, &connect_mac); } else { AJ_WarnPrintf(("AJ_WSL_NET_connect(): BAD WORK ITEM RECEIVED\n")); } AJ_WSL_WMI_FreeWorkItem(item); found = 1; } } } else { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item); AJ_WSL_WMI_FreeWorkItem(item); } AJ_BufListFree(connect, 1); return status; } }
static void run_buflist_coalesce(const struct test_case* test) { /* * verify the buffer list management */ AJ_BufList* list1 = AJ_BufListCreate(); AJ_BufNode* pNode1 = AJ_BufListCreateNode(100); AJ_BufNode* pNode2 = AJ_BufListCreateNode(200); AJ_AlwaysPrintf(("\n\n**************\nTEST: %s\n\n", __FUNCTION__)); memset(pNode1->buffer, 0x1, pNode1->length); memset(pNode2->buffer, 0x2, pNode2->length); AJ_BufListPushHead(list1, pNode1); AJ_BufListPushTail(list1, pNode2); AJ_BufNodeIterate(AJ_BufListNodePrint, list1, NULL); AJ_BufNodeIterate(AJ_BufListNodePrintDump, list1, NULL); AJ_BufListFree(list1, 1); // Test squeezing together a few buffer nodes in a list. AJ_AlwaysPrintf(("%s", "\n\nTEST: Coalesce Start\n")); { AJ_BufList* list3 = AJ_BufListCreate(); AJ_BufNode* pNodeA = AJ_BufListCreateNode(8); AJ_BufNode* pNodeB = AJ_BufListCreateNode(8); AJ_BufNode* pNodeC = AJ_BufListCreateNode(8); AJ_BufNode* pNodeD = AJ_BufListCreateNode(8); memset(pNodeA->buffer, 0xA1, 8); memset(pNodeB->buffer, 0xB2, 8); memset(pNodeC->buffer, 0xC3, 8); memset(pNodeD->buffer, 0xD4, 8); AJ_BufListPushHead(list3, pNodeA); AJ_BufListPushTail(list3, pNodeB); AJ_BufListPushTail(list3, pNodeC); AJ_BufListPushTail(list3, pNodeD); AJ_BufNodeIterate(AJ_BufListNodePrintDump, list3, NULL); AJ_AlwaysPrintf(("%s", "\n\nTEST: coalesce the head twice, then dump\n")); AJ_BufListCoalesce(list3->head); AJ_BufListCoalesce(list3->head); AJ_BufNodeIterate(AJ_BufListNodePrintDump, list3, NULL); AJ_AlwaysPrintf(("%s", "\n\nTEST: Next pull 16 bytes then dump\n")); AJ_BufListPullBytes(list3, 4); AJ_BufListPullBytes(list3, 4); AJ_BufListPullBytes(list3, 8); AJ_BufNodeIterate(AJ_BufListNodePrintDump, list3, NULL); AJ_AlwaysPrintf(("%s", "\n\nTEST: PULL BYTES 16 end\n")); AJ_BufListFree(list3, 1); } AJ_AlwaysPrintf(("%s", "\nTEST: Coalesce End\n")); }
AJ_EXPORT AJ_Status AJ_WSL_NET_connect(const char* SSID, const char* passphrase, WSL_NET_AUTH_MODE auth, WSL_NET_CRYPTO_TYPE crypto, uint8_t softAP) { AJ_Status status = AJ_OK; wsl_scan_list* list; list = (wsl_scan_list*)AJ_WSL_GetScanList(); AJ_WSL_NET_SetPowerMode(2); uint8_t bss_mac[6]; // Open auth does not require you to explicitly set the BSSID so this secondary scan is not needed if (!softAP) { if (auth != WSL_NET_AUTH_NONE) { AJ_Time timer; uint8_t found = 0; AJ_InitTimer(&timer); while (!found) { AJ_WSL_InitScanList(AJ_WSL_SCAN_LIST_SIZE); AJ_WSL_SetProbedSSID(SSID, 1); status = AJ_WSL_NET_scan(); // Some kind of scan error if (status != AJ_OK) { WSL_ClearScanList(); continue; } AJ_WSL_NET_scan_stop(); if (AJ_GetElapsedTime(&timer, TRUE) > AJ_WSL_CONNECT_TIMEOUT) { AJ_ErrPrintf(("AJ_WSL_NET_connect() Could not find the access point %s\n", SSID)); WSL_ClearScanList(); return AJ_ERR_FAILURE; } // Find the SSID you want to connect to in the second scan list if (getMacFromSSID(SSID, bss_mac, list)) { WSL_ClearScanList(); found = 1; break; } else { WSL_ClearScanList(); AJ_Sleep(AJ_WSL_CONNECT_WAIT); continue; } } if (crypto != WSL_NET_CRYPTO_WEP) { status = AJ_WSL_NET_SetPassphrase(SSID, passphrase, strlen(passphrase)); if (status != AJ_OK) { return status; } } } } { AJ_BufList* connect; AJ_BufList* connectOut; static const uint8_t zero_mac[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t connect_mac[6]; wsl_work_item* item = NULL; connect = AJ_BufListCreate(); /* Three different ways connect can be called. * 1. SoftAP: The devices mac is fetched and used * 2. Using Auth: The SSID's mac is found and used * 3. Open auth: A zero'ed mac is used */ if (softAP) { WSL_MarshalPacket(connect, WSL_SET_SOFT_AP, 0, 0x04, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, getDeviceMac(), 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else if ((auth != WSL_NET_AUTH_NONE) && (crypto != WSL_NET_CRYPTO_WEP)) { WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &bss_mac, 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else { // if the auth mode is open, use zero_mac, and set flags to zero WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &zero_mac, 0x0000, 0x0000); WMI_MarshalHeader(connect, 1, 1); } AJ_InfoPrintf(("AJ_WSL_NET_connect(): CONNECT\n")); AJ_WSL_WMI_PadPayload(connect); //AJ_BufListPrintDumpContinuous(connect); connectOut = AJ_BufListCreateCopy(connect); AJ_WSL_WMI_QueueWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), AJ_WSL_HTC_DATA_ENDPOINT1, connectOut); if (softAP) { AJ_AlwaysPrintf(("Waiting for a connection to the softAP %s\n", SSID)); memcpy(&connect_mac, (uint8_t*)getDeviceMac(), sizeof(connect_mac)); while (memcmp((uint8_t*)&connect_mac, (uint8_t*)getDeviceMac(), 6) == 0) { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item, AJ_TIMER_FOREVER); if (item && (status == AJ_OK)) { if (item->itemType == WSL_NET_CONNECT) { AJ_InfoPrintf(("AJ_WSL_NET_connect(): WORK ITEM RECEIVED\n")); uint16_t WMIEvent; uint32_t toss; uint16_t channel; WMI_Unmarshal(item->node->buffer, "quqM", &WMIEvent, &toss, &channel, &connect_mac); } else { AJ_WarnPrintf(("AJ_WSL_NET_connect(): BAD WORK ITEM RECEIVED\n")); } AJ_WSL_WMI_FreeWorkItem(item); } } } else { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item, AJ_TIMER_FOREVER); if (item && (status == AJ_OK)) { AJ_WSL_WMI_FreeWorkItem(item); } } AJ_BufListFree(connect, 1); return status; } }
static void run_wsl_htc_parsing(const struct test_case* test) { /* * create a chain of buffers that simulate each protocol layer wrapping the layer above it. * The values chosen to populate the buffers are not legal protocol values, they just show * where the bytes are laid out in memory. */ AJ_BufList* list2 = AJ_BufListCreate(); AJ_BufNode* pNodeAppData = AJ_BufListCreateNodeZero(16, 1); AJ_BufNode_WMI* pNodeWMI; AJ_BufNode* pNodeWMITrail; AJ_BufNode* pNodeHTC; wsl_htc_msg_connect_service* msgConnectService; AJ_BufNode* pNodeHTCTrail; AJ_BufNode* pNodeHTCHeader; wsl_htc_hdr* msgHdr; AJ_AlwaysPrintf(("\n\n**************\nTEST: %s\n\n", __FUNCTION__)); strcpy((char*)pNodeAppData->buffer, "AppData string"); pNodeWMI = AJ_BufListCreateNode(sizeof(wsl_spi_command)); // stuff the buffer with a command. ((wsl_spi_command*)pNodeWMI->buffer)->cmd_addr = AJ_WSL_SPI_SPI_STATUS; ((wsl_spi_command*)pNodeWMI->buffer)->cmd_rx = 1; ((wsl_spi_command*)pNodeWMI->buffer)->cmd_reg = 1; *((uint16_t*)pNodeWMI->buffer) = CPU_TO_BE16(*(uint16_t*)pNodeWMI->buffer); // Swap the bytes around // create a bogus trailer pNodeWMITrail = AJ_BufListCreateNode(8); memset(pNodeWMITrail->buffer, 0xA1, 8); // create an HTC command pNodeHTC = AJ_BufListCreateNode(sizeof(wsl_htc_msg_connect_service)); msgConnectService = (wsl_htc_msg_connect_service*)pNodeHTC->buffer; msgConnectService->msg.messageID = AJ_WSL_HTC_CONNECT_SERVICE_ID; msgConnectService->serviceID = 0x5678; // random choice msgConnectService->flags = 0xCDEF; // random choice msgConnectService->serviceMetadataLength = 0; // random choice msgConnectService->metadata = 0; // random choice AJ_WSL_HTC_MSG_CONNECT_TO_WIRE(msgConnectService); // create another bogus trailer pNodeHTCTrail = AJ_BufListCreateNode(8); memset(pNodeHTCTrail->buffer, 0xB2, 8); // AppData was added then WMI was added, then HTC wrapped around that AJ_BufListPushHead(list2, pNodeAppData); AJ_BufListPushHead(list2, pNodeWMI); AJ_BufListPushTail(list2, pNodeWMITrail); AJ_BufListPushHead(list2, pNodeHTC); AJ_BufListPushTail(list2, pNodeHTCTrail); // create an HTC header structure with the correct size field (based on the size of the data to send on the wire) pNodeHTCHeader = AJ_BufListCreateNode(sizeof(wsl_htc_hdr)); msgHdr = (wsl_htc_hdr*)pNodeHTCHeader->buffer; msgHdr->endpointID = AJ_WSL_HTC_CONTROL_ENDPOINT; msgHdr->flags = 0; msgHdr->controlBytes[0] = 0xAB; msgHdr->controlBytes[1] = 0xCD; msgHdr->payloadLength = AJ_BufListLengthOnWire(list2); AJ_WSL_HTC_HDR_TO_WIRE(msgHdr); AJ_AlwaysPrintf(("\n\nPayload size would be: %d\n\n", AJ_BufListLengthOnWire(list2))); AJ_BufListPushHead(list2, pNodeHTCHeader); AJ_AlwaysPrintf(("%s", "write this to the wire\n\n")); AJ_BufListIterateOnWire(AJ_BufListWriteToWire_Simulated, list2, &toTarget); AJ_AlwaysPrintf(("\n\nDone wire write, length on wire: %d\n\n", AJ_BufListLengthOnWire(list2))); AJ_BufListFree(list2, 1); /* { // simulate a number of reads from the SPI buffer fakeWireRead = fakeWireBuffer; uint16_t readBufferSize = sizeof(fakeWireBuffer); AJ_AlwaysPrintf(("%s", "Wire Bufer\n")); while (readBufferSize > 0) { uint8_t byteRead = AJ_BufListReadByteFromWire_Simulated(); AJ_AlwaysPrintf(("%02X ", byteRead)); readBufferSize--; } } */ toTarget.fakeWireRead = toTarget.fakeWireBuffer; // fakeWireRead = fakeWireBuffer; // reset the read pointer to the start of our buffer { wsl_htc_hdr htcHdr1; AJ_BufNode* pNodeHTCBody; wsl_htc_msg* htcMsg1; AJ_AlwaysPrintf(("%s", "Read HTC header from wire buffer\n")); AJ_BufListReadBytesFromWire_Simulated(sizeof(htcHdr1), (uint8_t*)&htcHdr1, &toTarget); // convert the fields to the correct endianness AJ_WSL_HTC_HDR_FROM_WIRE(&htcHdr1); AJ_AlwaysPrintf(("\n HTC Hdr payload length 0x%04x\n\n", htcHdr1.payloadLength)); AJ_AlwaysPrintf(("%s", "Read HTC from wire buffer\n")); pNodeHTCBody = AJ_BufListCreateNode(htcHdr1.payloadLength /*+ sizeof(wsl_htc_msg)*/); htcMsg1 = (wsl_htc_msg*)pNodeHTCBody->buffer; AJ_BufListReadBytesFromWire_Simulated(pNodeHTCBody->length, pNodeHTCBody->buffer, &toTarget); switch (htcHdr1.endpointID) { case AJ_WSL_HTC_CONTROL_ENDPOINT: AJ_AlwaysPrintf(("%s", "Read HTC control endpoint\n")); // break; case AJ_WSL_HTC_DATA_ENDPOINT1: case AJ_WSL_HTC_DATA_ENDPOINT2: case AJ_WSL_HTC_DATA_ENDPOINT3: case AJ_WSL_HTC_DATA_ENDPOINT4: AJ_AlwaysPrintf(("\n%s %d\n", "Read HTC data endpoint", htcHdr1.endpointID)); // TODO send the data up to the next API level AJ_WSL_WMI_PrintMessage(pNodeHTCBody); break; default: AJ_AlwaysPrintf(("%s %d", "UNKNOWN Endpoint", htcHdr1.endpointID)); break; } // AJ_BufListReadBytesFromWire_Simulated(pNodeHTCBody->length, pNodeHTCBody->buffer); AJ_WSL_HTC_MSG_FROM_WIRE(htcMsg1); switch (htcMsg1->messageID) { case AJ_WSL_HTC_MSG_READY_ID: { wsl_htc_msg_ready* htcMsgReady1 = (wsl_htc_msg_ready*)pNodeHTCBody->buffer; AJ_AlwaysPrintf(("%s", "Read HTC msg AJ_WSL_HTC_MSG_READY_ID \n")); AJ_WSL_HTC_MSG_READY_FROM_WIRE(htcMsgReady1); AJ_AlwaysPrintf(("\n HTC connect service message 0x%04x, CreditCount 0x%04X CreditSize 0x%04X\n\n", htcMsgReady1->msg.messageID, htcMsgReady1->creditCount, htcMsgReady1->creditSize)); break; } case AJ_WSL_HTC_CONNECT_SERVICE_ID: { wsl_htc_msg_connect_service* htcMsgCS1 = (wsl_htc_msg_connect_service*) pNodeHTCBody->buffer; AJ_AlwaysPrintf(("%s", "Read HTC msg AJ_WSL_HTC_CONNECT_SERVICE_ID \n")); AJ_WSL_HTC_MSG_CONNECT_FROM_WIRE(htcMsgCS1); AJ_AlwaysPrintf(("\n HTC connect service message 0x%04x, serviceID 0x%04X \n\n", htcMsgCS1->msg.messageID, htcMsgCS1->serviceID)); break; } case AJ_WSL_HTC_SERVICE_CONNECT_RESPONSE_ID: { wsl_htc_msg_service_connect_response* htcServiceConnectResponse1 = (wsl_htc_msg_service_connect_response*)pNodeHTCBody->buffer; AJ_AlwaysPrintf(("%s", "Read HTC msg AJ_WSL_HTC_SERVICE_CONNECT_RESPONSE_ID \n")); AJ_WSL_HTC_MSG_SERVICE_CONNECT_RESPONSE_FROM_WIRE(htcServiceConnectResponse1); AJ_AlwaysPrintf(("\n HTC service connect response 0x%04x, serviceID 0x%04X metadatalength 0x%04X\n\n", htcServiceConnectResponse1->msg.messageID, htcServiceConnectResponse1->serviceID, htcServiceConnectResponse1->serviceMetadataLength)); break; } case AJ_WSL_HTC_SETUP_COMPLETE_ID: { AJ_AlwaysPrintf(("%s", "Read HTC msg AJ_WSL_HTC_SETUP_COMPLETE_ID \n")); break; } case AJ_WSL_HTC_HOST_READY_ID: { AJ_AlwaysPrintf(("%s", "Read HTC msg AJ_WSL_HTC_HOST_READY_ID \n")); break; } default: { AJ_ASSERT(htcMsg1->messageID <= AJ_WSL_HTC_HOST_READY_ID); break; } } } }