Beispiel #1
0
//Mailbox Read Steps:
//1. Interrupt going from the QCA4002 to the SPI host.
//2. INTERNAL read from INTR_CAUSE register.
//3. INTERNAL read from RDBUF_BYTE_AVA register.
//4. Internal read from RDBUF_LOOKAHEAD1 register
//5. Internal read from RDBUF_LOOKAHEAD2 register. From the 4 bytes we have read from RDBUF_LOOKAHEAD registers, get the packet size.
//6. INTERNAL write to DMA_SIZE register with the packet size.
//7. Start DMA read command and start reading the data by de-asserting chip select pin.
//8. The packet available will be cleared by HW at the end of the DMA read.
//
AJ_EXPORT AJ_Status AJ_WSL_ReadFromMBox(uint8_t box, uint16_t* len, uint8_t** buf)
{
    AJ_Status status = AJ_ERR_SPI_READ;
    uint16_t cause = 0;
    uint16_t bytesInBuffer = 0;
    uint16_t bytesToRead = 0;
    uint16_t lookAhead;
    uint16_t payloadLength;

    AJ_ASSERT(0 == box);
    AJ_EnterCriticalRegion();
    //2. INTERNAL read from INTR_CAUSE register.
    do {

        //3. INTERNAL read from RDBUF_BYTE_AVA register.
        status = AJ_WSL_SPI_RegisterRead(AJ_WSL_SPI_REG_RDBUF_BYTE_AVA, &bytesInBuffer);

        AJ_ASSERT(status == AJ_OK);
        //bytesInBuffer = CPU_TO_BE16(bytesInBuffer);

        // The first few bytes of the packet can now be examined and the right amount of data read from the target
        //4. Internal read from RDBUF_LOOKAHEAD1 register
        //5. Internal read from RDBUF_LOOKAHEAD2 register. From the 4 bytes we have read from RDBUF_LOOKAHEAD registers, get the packet size.
        status = AJ_WSL_SPI_RegisterRead(AJ_WSL_SPI_REG_RDBUF_LOOKAHEAD1, &lookAhead);
        AJ_ASSERT(status == AJ_OK);
        lookAhead = CPU_TO_BE16(lookAhead);

        status = AJ_WSL_SPI_RegisterRead(AJ_WSL_SPI_REG_RDBUF_LOOKAHEAD2, &payloadLength);
        AJ_ASSERT(status == AJ_OK);
        payloadLength = CPU_TO_BE16(payloadLength);

        // calculate number of bytes to read from the lookahead info, and round up to the next block size
        bytesToRead = payloadLength + 6; //sizeof(header);
        bytesToRead = ((bytesToRead / AJ_WSL_MBOX_BLOCK_SIZE) + ((bytesToRead % AJ_WSL_MBOX_BLOCK_SIZE) ? 1 : 0)) * AJ_WSL_MBOX_BLOCK_SIZE;
        *buf = (uint8_t*)AJ_WSL_Malloc(bytesToRead);
        *len = bytesToRead;
        //6. INTERNAL write to DMA_SIZE register with the packet size.
        // write size to be transferred
        status = AJ_WSL_SetDMABufferSize(bytesToRead);
        AJ_ASSERT(status == AJ_OK);

        AJ_WSL_SPI_ReadIntoBuffer(bytesToRead, buf);

        // clear the packet available interrupt
        cause = 0x1;
        status = AJ_WSL_SPI_RegisterWrite(AJ_WSL_SPI_REG_INTR_CAUSE, cause);
        AJ_ASSERT(status == AJ_OK);

        break;

    } while (0);
    AJ_LeaveCriticalRegion();
    return status;
}
Beispiel #2
0
int8_t IP_GenerateUnicast(uint8_t packet[], IP_Protocol_t protocol, const IP_Address_t *destinationIP, uint8_t payloadLength)
{
	const IP_Address_t *routerIP = destinationIP;
	if(!(IP_compareNet(&OwnIPAddress, destinationIP)))
		routerIP = &RouterIPAddress;

	int8_t offset = Ethernet_GenerateUnicast(packet, routerIP, CPU_TO_BE16(ETHERTYPE_IPV4));
	if(offset <= 0)
		return offset;

	return offset + IP_WriteHeader(packet + offset, protocol, destinationIP, payloadLength);
}
Beispiel #3
0
uint16_t IP_Checksum(const void *data, uint16_t length)
{
	const uint16_t *Words = (const uint16_t *)data;
	uint16_t length16 = length / 2;
	uint16_t Checksum = 0;

	while(length16--)
		IP_ChecksumAdd(&Checksum, *(Words++));

	if(length & 1)
		IP_ChecksumAdd(&Checksum, *Words & CPU_TO_BE16(0xFF00));

	return ~Checksum;
}
Beispiel #4
0
bool ICMP_ProcessPacket(uint8_t packet[])
{
	// Length is already checked
	ICMP_Header_t *ICMP = (ICMP_Header_t *)packet;

	if(ICMP->Type != ICMP_Echo_Request || ICMP->Code != ICMP_ECHO_Code)
		return false;

	// Answer Request: Leave Packet as is, only replace Type
	ICMP->Type = ICMP_Echo_Reply;
	// Adjust Checksum, only difference is Request(8)-Reply(0) at high byte
	IP_ChecksumAdd(&ICMP->Checksum, CPU_TO_BE16((ICMP_Echo_Request - ICMP_Echo_Reply) << 8));

	return true;
}
Beispiel #5
0
AJ_Status AJ_WSL_SPI_RegisterRead(uint16_t reg, uint8_t* spi_data)
{
    aj_spi_status rc;
    wsl_spi_command send;
    AJ_Status status = AJ_ERR_SPI_READ;
    uint8_t pcs = AJ_WSL_SPI_PCS;

    // initialize an SPI CMD structure with the register of interest
    send.cmd_rx = AJ_WSL_SPI_READ;
    send.cmd_reg = AJ_WSL_SPI_INTERNAL;
    send.cmd_addr = reg;
    /* Test write: should return OK. */
    rc = AJ_SPI_WRITE(AJ_WSL_SPI_DEVICE, *((uint8_t*)&send + 1), AJ_WSL_SPI_PCS, AJ_WSL_SPI_CONTINUE);
    AJ_ASSERT(rc == SPI_OK);
    rc = AJ_SPI_READ(AJ_WSL_SPI_DEVICE, spi_data, &pcs); // toss.
    AJ_ASSERT(rc == SPI_OK);
    rc = AJ_SPI_WRITE(AJ_WSL_SPI_DEVICE, *(uint8_t*)&send, AJ_WSL_SPI_PCS, AJ_WSL_SPI_END);
    AJ_ASSERT(rc == SPI_OK);
    rc = AJ_SPI_READ(AJ_WSL_SPI_DEVICE, spi_data, &pcs); // toss.
    AJ_ASSERT(rc == SPI_OK);

    // read the first byte of response
    rc = AJ_SPI_WRITE(AJ_WSL_SPI_DEVICE, 0 /*xFF*/, AJ_WSL_SPI_PCS, AJ_WSL_SPI_CONTINUE); // junk to write while reading
    AJ_ASSERT(rc == SPI_OK);
    if (rc == SPI_OK) {
        /* Test read: should return OK with what is sent. */
        rc = AJ_SPI_READ(AJ_WSL_SPI_DEVICE, spi_data, &pcs);
        AJ_ASSERT(rc == SPI_OK);
        status = AJ_OK;
    }

    // read the second byte
    spi_data++;
    rc = AJ_SPI_WRITE(AJ_WSL_SPI_DEVICE, 0 /*xFF*/, AJ_WSL_SPI_PCS, AJ_WSL_SPI_CONTINUE); // junk to write while reading
    AJ_ASSERT(rc == SPI_OK);
    if (rc == SPI_OK) {
        /* Test read: should return OK with what is sent. */
        rc = AJ_SPI_READ(AJ_WSL_SPI_DEVICE, spi_data, &pcs);
        AJ_ASSERT(rc == SPI_OK);
        status = AJ_OK;
    }
    spi_data--; // move back to the original location
    *(uint16_t*)spi_data = CPU_TO_BE16(*(uint16_t*)spi_data);
    return status;
}
Beispiel #6
0
static uint8_t IP_WriteHeader(uint8_t packet[], IP_Protocol_t protocol, const IP_Address_t *destinationIP, uint16_t payloadLength)
{
	IP_Header_t *IP = (IP_Header_t *)packet;

	IP->Version_IHL		= IP_VERSION_IHL;
	IP->TypeOfService	= 0;
	IP->Length		= cpu_to_be16(sizeof(IP_Header_t) + payloadLength);
	IP->Identification	= 0;
	IP->FlagsFragment	= CPU_TO_BE16(IP_FLAGS_DONTFRAGMENT);
	IP->TTL			= DEFAULT_TTL;
	IP->Protocol		= protocol;
	IP->DestinationAddress	= *destinationIP;	// Can be an alias of IP->SourceAddress
	IP->SourceAddress	= OwnIPAddress;
	IP->Checksum		= 0;			// First set it to 0, then calculate correct checksum
	IP->Checksum		= IP_Checksum(IP, sizeof(IP_Header_t));

	return sizeof(IP_Header_t);
} 
Beispiel #7
0
bool IP_ProcessPacket(uint8_t packet[], uint16_t length)
{
	// Minimum length is already checked
	IP_Header_t *IP = (IP_Header_t *)packet;

	// Remove optional padding
	uint16_t ip_length = be16_to_cpu(IP->Length);

	if(IP->Version_IHL != IP_VERSION_IHL ||
	  (IP->FlagsFragment & CPU_TO_BE16(0x3FFF) ||
	   ip_length > length))
		return false;

	if(IP->DestinationAddress != OwnIPAddress && IP->DestinationAddress != BroadcastIPAddress)
		return false;

	length = ip_length - sizeof(IP_Header_t);
	bool reflect;
	switch (IP->Protocol)
	{
		case IP_PROTOCOL_ICMP:
			reflect = ICMP_ProcessPacket(IP->data);
			break;
		case IP_PROTOCOL_UDP:
			reflect = UDP_ProcessPacket(IP->data, &IP->SourceAddress, length);
			break;
		default:
			return false;
	}

	if(reflect)	// rewrite Header, replace destination with sourceAddress
	{
		IP_WriteHeader(packet, IP->Protocol, &IP->SourceAddress, length);
		return true;
	} else {
		return false;
	}
}
Beispiel #8
0
uint8_t IP_GenerateBroadcast(uint8_t packet[], IP_Protocol_t protocol, uint8_t payloadLength)
{
	uint8_t offset = Ethernet_GenerateBroadcast(packet, CPU_TO_BE16(ETHERTYPE_IPV4));

	return offset + IP_WriteHeader(packet + offset, protocol, &BroadcastIPAddress, payloadLength);
}
 *  by the Serial Port service in its text string attributes.
 */
static const struct
{
    SDP_ItemSequence8Bit_t LanguageEncoding_Header;
    struct
    {
        SDP_Item16Bit_t    LanguageID;
        SDP_Item16Bit_t    EncodingID;
        SDP_Item16Bit_t    OffsetID;
    } LanguageEncoding;
} ATTR_PACKED PROGMEM SerialPort_Attribute_LanguageBaseIDOffset =
{
    SDP_ITEMSEQUENCE8BIT(sizeof(SerialPort_Attribute_LanguageBaseIDOffset.LanguageEncoding)),
    {
        SDP_ITEM16BIT(SDP_DATATYPE_UnsignedInt, CPU_TO_BE16(0x454E)),
        SDP_ITEM16BIT(SDP_DATATYPE_UnsignedInt, CPU_TO_BE16(0x006A)),
        SDP_ITEM16BIT(SDP_DATATYPE_UnsignedInt, CPU_TO_BE16(0x0100)),
    },
};

/** Serial Port Profile attribute, listing a human readable name of the service. */
static const struct
{
    SDP_ItemString8Bit_t Text_Header;
    char                 Text[];
} ATTR_PACKED PROGMEM SerialPort_Attribute_ServiceName =
{
    SDP_ITEMSTRING("Wireless Serial Port"),
};
Beispiel #10
0
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;
            }
        }
    }
}