Пример #1
0
/*
*********************************************************************************************************
*                                   ScratchUnmount()
*    
* Description : Unmounts Scratch from the specified RAW window.
*
* Argument(s) : rawId -- RAW window ID that scratch had been mounted to.
*
* Return(s)   : None
*
* Caller(s)   : WF Driver
*
* Notes:      : None
*
*********************************************************************************************************
*/
void ScratchUnmount(UINT8 rawId)
{
    RawMove(rawId, RAW_SCRATCH_POOL, FALSE, 0);
    if (rawId == RAW_RX_ID)
    {
        SetRawWindowState(RAW_RX_ID, WF_RAW_UNMOUNTED);
    }
    else
    {
        SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);        
    }    
        
}    
Пример #2
0
/*
*********************************************************************************************************
*                                   ScratchUnmount()
*    
* Description : Unmounts Scratch from the specified RAW window.
*
* Argument(s) : rawId -- RAW window ID that scratch had been mounted to.
*
* Return(s)   : None
*
* Caller(s)   : WF Driver
*
* Notes:      : None
*
*********************************************************************************************************
*/
void ScratchUnmount(uint8_t rawId)
{
    RawMove(rawId, RAW_SCRATCH_POOL, false, 0);
    if (rawId == RAW_RX_ID)
    {
        SetRawWindowState(RAW_RX_ID, WF_RAW_UNMOUNTED);
    }
    else
    {
        SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);        
    }    
        
}    
Пример #3
0
BOOL AllocateMgmtTxBuffer(UINT16 bytesNeeded)
{
    UINT16 bufAvail;
    UINT16 byteCount;
    
    /* get total bytes available for MGMT tx memory pool */
    bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT1_REG) & 0x0fff; /* LS 12 bits contain length */                    
    
    /* if enough bytes available to allocate */
    if ( bufAvail >= bytesNeeded )
    {
        /* allocate and create the new Tx buffer (mgmt or data) */
        byteCount = RawMove(RAW_TX_ID, RAW_MGMT_POOL, TRUE, bytesNeeded);
        WF_ASSERT(byteCount != 0);
    }
    /* else not enough bytes available at this time to satisfy request */
    else
    {
        return FALSE;
    }
    
    RawWindowReady[RAW_TX_ID] = TRUE;
    SetRawWindowState(RAW_TX_ID, WF_RAW_MGMT_MOUNTED);
    
    return TRUE;
}    
Пример #4
0
bool AllocateDataTxBuffer(uint16_t bytesNeeded)
{
    uint16_t bufAvail;
    uint16_t byteCount;
    
    /* Ensure the MRF24W is awake (only applies if PS-Poll was enabled) */
    EnsureWFisAwake();
    
    /* get total bytes available for DATA tx memory pool */
    bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT0_REG) & 0x0fff; /* LS 12 bits contain length */                    
    
        /* if enough bytes available to allocate */
    if ( bufAvail >= bytesNeeded )
    {
        /* allocate and create the new Tx buffer (mgmt or data) */
        byteCount = RawMove(RAW_TX_ID, RAW_DATA_POOL, true, bytesNeeded);
        SYS_ASSERT(byteCount != 0, "");
    }
    /* else not enough bytes available at this time to satisfy request */
    else
    {
        return false;
    }
    
    RawWindowReady[RAW_TX_ID] = true;
    SetRawWindowState(RAW_TX_ID, WF_RAW_DATA_MOUNTED);
    return true;

}    
Пример #5
0
/*****************************************************************************
 * FUNCTION: WaitForMgmtRespAndReadData
 *
 * RETURNS:  None
 *
 * PARAMS:   expectedSubtype -- management message subtype that we are expecting
 *           p_data          -- pointer where any desired management data bytes 
 *                              will be written
 
 *           numDataBytes    -- Number of data bytes from mgmt response to write to
 *                              p_data.  Data always starts at index 4 of mgmt response.
 *           skipDataRead    -- if TRUE, then no data will be read and the mgmt buffer will not
 *                              be freed.  If FALSE, the data will be read and the mgmt buffer
 *                              will be freed.
 *
 *  NOTES:   Waits for the mgmt response message and validates it by:
 *             1) checking the result field
 *             2) verifying that the received subtype matches the execpted subtype
 *
 *            In addition, this function reads the desired number of data bytes from 
 *            the mgmt response, copies them to p_data, and then frees the mgmt buffer. 
 *****************************************************************************/
void WaitForMgmtResponseAndReadData(UINT8 expectedSubtype, 
                                    UINT8 numDataBytes,  
                                    UINT8 startIndex, 
                                    UINT8 *p_data)

{
    tMgmtMsgRxHdr  hdr;  /* management msg header struct */
    
    WaitForMgmtResponse(expectedSubtype, DO_NOT_FREE_MGMT_BUFFER);
        
    /* if made it here then received a management message */
    RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr);

    /* check header result and subtype fields */
    WF_ASSERT(hdr.result  == WF_SUCCESS || hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR);
    WF_ASSERT(hdr.subtype == expectedSubtype);

    /* if caller wants to read data from this mgmt response */
    if (numDataBytes > 0) 
    {
        RawRead(RAW_RX_ID, startIndex, numDataBytes, p_data);  
    }    
    
    /* free the mgmt buffer */    
    DeallocateMgmtRxBuffer();
    
     /* if there was a mounted data packet prior to the mgmt tx/rx transaction, then restore it */    
    if (RestoreRxData == TRUE)
    {
        RestoreRxData = FALSE;
        PopRawWindow(RAW_RX_ID);
        SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED); 
    }          
}
Пример #6
0
/* If a data message mounted in RAW window then will be transmitted to 802.11 network */
void RawSendTxBuffer(UINT16 len)
{
    RawMove(RAW_TX_ID, RAW_MAC, FALSE, len);
    RawWindowReady[RAW_TX_ID] = FALSE;
    SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);

} 
Пример #7
0
bool AllocateMgmtTxBuffer(uint16_t bytesNeeded)
{
    uint16_t bufAvail;
    uint16_t byteCount;

    /* get total bytes available for MGMT tx memory pool */
    bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT1_REG) & 0x0fff; /* LS 12 bits contain length */

    /* if enough bytes available to allocate */
    if ( bufAvail >= bytesNeeded )
    {
        /* allocate and create the new Tx buffer (mgmt or data) */
        byteCount = RawMove(RAW_TX_ID, RAW_MGMT_POOL, true, bytesNeeded);
        if (byteCount == 0)
            return false; // just return and let host retry again
    }
    /* else not enough bytes available at this time to satisfy request */
    else
    {
        return false;
    }

    RawWindowReady[RAW_TX_ID] = true;
    SetRawWindowState(RAW_TX_ID, WF_RAW_MGMT_MOUNTED);

    return true;
}
Пример #8
0
/*****************************************************************************
  Function:
	BOOL AllocateDataTxBuffer(UINT16 bytesNeeded)

  Summary:
	Allocates a Data Tx buffer for use by the TCP/IP stack.

  Description:
    Determines if WiFi chip has enough memory to allocate a tx data buffer, and, 
    if so, allocates it.

  Precondition:
	None

  Parameters:
	bytesNeeded -- number of bytes needed for the data tx message
	             
  Returns:
  	True if data tx buffer successfully allocated, else False
  	
  Remarks:
	None
*****************************************************************************/
BOOL AllocateDataTxBuffer(UINT16 bytesNeeded)
{
    UINT16 bufAvail;
    UINT16 byteCount;
    
    WF_ASSERT(GetRawWindowState(RAW_DATA_TX_ID) != WF_RAW_DATA_MOUNTED);
    
    /* Ensure the MRF24W is awake (only applies if PS-Poll was enabled) */
    EnsureWFisAwake();

    
    /* get total bytes available for DATA tx memory pool */
    bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT0_REG) & 0x0fff; /* LS 12 bits contain length */                    
    
    /* if enough bytes available to allocate */
    if ( bufAvail >= bytesNeeded )
    {
        /* allocate and create the new Tx buffer (mgmt or data) */
        byteCount = RawMove(RAW_DATA_TX_ID, RAW_DATA_POOL, TRUE, bytesNeeded);
        WF_ASSERT(byteCount != 0);
        
        /* flag this raw window as mounted (in use) */
        SetRawWindowState(RAW_DATA_TX_ID, WF_RAW_DATA_MOUNTED);
        return TRUE;

    }
    /* else not enough bytes available at this time to satisfy request */
    else
    {
        return FALSE;
    }

}    
Пример #9
0
/* If a data message mounted in RAW window then will be transmitted to 802.11 network */
void RawSendTxBuffer(uint16_t len)
{
    RawMove(RAW_TX_ID, RAW_MAC, false, len);
    RawWindowReady[RAW_TX_ID] = false;
    SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);

} 
Пример #10
0
/*****************************************************************************
 * FUNCTION: SendMgmtMsg
 *
 * RETURNS:  error code
 *
 * PARAMS:   p_header      -- pointer to mgmt message header data
 *           headerLength  -- number of bytes in the header
 *                              will be written
 *           p_data        -- pointer to mgmt message data
 *           dataLength    -- number of byte of data
 *
 *  NOTES:   Sends a management message
 *****************************************************************************/
void SendMgmtMsg(UINT8 *p_header,
                 UINT8 headerLength,
                 UINT8 *p_data,
                 UINT8 dataLength)
{
    #if defined(__18CXX)
        static UINT32  startTickCount;   
        static UINT32  maxAllowedTicks;  
    #else
        UINT32  startTickCount;   
        UINT32  maxAllowedTicks;  
    #endif


    /* cannot send management messages while in WF_ProcessEvent() */
    WF_ASSERT(!isInWFProcessEvent());
    
    EnsureWFisAwake();
    
    /* if a Rx Data packet is mounted that has not yet been processed */
    if (GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED)
    {
        /* save it, so after mgmt response received it can be restored */
        PushRawWindow(RAW_RX_ID);
        RestoreRxData = TRUE;     
    }    


    /* mounts a tx mgmt buffer on the MRF24W when data tx is done */
    maxAllowedTicks = TICKS_PER_SECOND / 200;  /* 5 ms timeout */
    startTickCount = (UINT32)TickGet();
    while (!WFisTxMgmtReady() )
    {
        MACProcess();
        
        /* DEBUG -- REMOVE AFTER FIGURE OUT WHY TIMING OUT (RARELY HAPPENS) */
        if (TickGet() - startTickCount >= maxAllowedTicks)
        {
            /* force flags so WFisTxMgmtReady will return TRUE */
            SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
            RawWindowReady[RAW_TX_ID] = FALSE;
        }    
    }    

    /* write out management header */
    RawSetByte(RAW_TX_ID, p_header, headerLength); 
    
    /* write out data (if any) */
    if (dataLength > 0)
    {
        RawSetByte(RAW_TX_ID, p_data, dataLength);         
    }  

    /* send mgmt msg to MRF24W */
    SendRAWManagementFrame(headerLength + dataLength);
}                           
Пример #11
0
/* mounts the most recent Rx message.  Could be a management or data message. */
uint16_t RawMountRxBuffer(void)
{
    uint16_t length;

    length = RawMove(RAW_RX_ID, RAW_MAC, true, 0);

    RawWindowReady[RAW_RX_ID] = true;
    SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED);

    return length;
}
Пример #12
0
/* mounts the most recent Rx message.  Could be a management or data message. */
UINT16 RawMountRxBuffer(void)
{
    UINT16 length;
    
    length = RawMove(RAW_RX_ID, RAW_MAC, TRUE, 0);
    
    RawWindowReady[RAW_RX_ID] = TRUE;
    SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED);
    
    
    return length;
} 
Пример #13
0
/*****************************************************************************
 * FUNCTION: WaitForMgmtResponse
 *
 * RETURNS:  None
 *
 * PARAMS:   expectedSubtype -- The expected subtype of the mgmt response
 *           freeAction      -- FREE_MGMT_BUFFER or DO_NOT_FREE_MGMT_BUFFER
 *
 *  NOTES:   Called after sending a mgmt request.  This function waits for a mgmt
 *           response.  The caller can optionally request the the management 
 *           response be freed immediately (by this function) or not freed.  If not
 *           freed the caller is responsible to free the response buffer.
 *****************************************************************************/
void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction)
{
    tMgmtMsgRxHdr  hdr;
    
    /* Wait until mgmt response is received */
    while (gMgmtConfirmMsgReceived == FALSE)
    {
        WFProcess();
        
        /* if received a data packet while waiting for mgmt packet */
        if (g_HostRAWDataPacketReceived)
        {
            /* loop until stack has processed the received data message */
            while (g_HostRAWDataPacketReceived)      
            {
                StackTask(); 
            }    

            /* ensure interrupts enabled */
            WF_EintEnable();
        }    
    }    
 
    /* set this back to FALSE so the next mgmt send won't think he has a response before one is received */
    gMgmtConfirmMsgReceived = FALSE;
    
    
    /* if the caller wants to delete the response immediately (doesn't need any data from it */
    if (freeAction == FREE_MGMT_BUFFER)
    {
        /* read and verify result before freeing up buffer to ensure our message send was successful */
        RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr);
               
        /* Mgmt response 'result' field should always indicate success.  If this assert is hit the error codes are located */
        /* WFApi.h.  Search for WF_SUCCESS for the list of error codes.                                                    */
        WF_ASSERT(hdr.result == WF_SUCCESS);

        /* mgmt response subtype had better match subtype we were expecting */
        WF_ASSERT(hdr.subtype == expectedSubtype);

        /* free mgmt buffer */
        DeallocateMgmtRxBuffer();        
        
        /* if there was a mounted data packet prior to the mgmt tx/rx transaction, then restore it */
        if (RestoreRxData == TRUE)
        {
            RestoreRxData = FALSE;
            PopRawWindow(RAW_RX_ID);
            SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED); 
        }          
    }   
}  
Пример #14
0
/*****************************************************************************
  Function:
	void DeallocateDataRxBuffer(void)

  Summary:
	Deallocates a Data Rx buffer

  Description:
    Typically called by MACGetHeader(), the assumption being that when the stack
    is checking for a newly received data message it is finished with the previously
    received data message.  Also called by MACGetHeader() if the SNAP header is invalid
    and the packet is thrown away.

  Precondition:
	None

  Parameters:
	None
	             
  Returns:
  	None
  	
  Remarks:
	None
*****************************************************************************/
void DeallocateDataRxBuffer(void)
{
    WF_ASSERT(GetRawWindowState(RAW_DATA_RX_ID) == WF_RAW_DATA_MOUNTED);
    
    /* perform deallocation of raw rx buffer */
    RawMove(RAW_DATA_RX_ID, RAW_DATA_POOL, FALSE, 0);

    /* set state flag */
    SetRawWindowState(RAW_DATA_RX_ID, WF_RAW_UNMOUNTED);
    
    /* the current length of the Rx data packet is now 0 (used by MAC) */
    SetRxDataPacketLength(0);
}    
Пример #15
0
/*
*********************************************************************************************************
*                                   ScratchMount()
*
* Description : Mounts Scratch using the specified RAW window.
*
* Argument(s) : rawId -- desired RAW window to mount Scratch to.
*
* Return(s)   : None
*
* Caller(s)   : WF Driver
*
* Notes:      : None
*
*********************************************************************************************************
*/
uint16_t ScratchMount(uint8_t rawId)
{
    uint16_t byteCount;

    byteCount = RawMove(rawId, RAW_SCRATCH_POOL, true, 0);
    if (byteCount == 0)
    {
        /* work-around, somehow the scratch was already mounted to the other raw window */
        rawId = !rawId;
        //   WF_ASSERT(byteCount > 0);  /* scratch mount should always return value > 0 */
    }

    SetRawWindowState(rawId, WF_SCRATCH_MOUNTED);
    return byteCount;
}
Пример #16
0
/*****************************************************************************
  Function:
	UINT16 RawMountRxBuffer(UINT8 rawId)

  Summary:
	Mounts most recent Rx message.

  Description:
    This function mounts the most recent Rx message from the WiFi chip, which
    could be either a management or a data message.  

  Precondition:
	None

  Parameters:
	rawId -- RAW ID specifying which raw window to mount the rx packet in.
	             
  Returns:
  	length -- number of bytes in the received message.
  	
  Remarks:
	None
*****************************************************************************/
UINT16 RawMountRxBuffer(UINT8 rawId)
{
    UINT16 length;
    
    length = RawMove(rawId, RAW_MAC, TRUE, 0);
    WF_ASSERT(length > 0);
    
    /* if mounting a Raw Rx data frame */
    if (rawId == RAW_DATA_RX_ID)
    {
        /* notify WiFi driver that an Rx data frame is mounted */
        SetRawWindowState(RAW_DATA_RX_ID, WF_RAW_DATA_MOUNTED);
    }    

    return length;
} 
Пример #17
0
/*****************************************************************************
  Function:
	void SendRAWDataFrame(UINT16 bufLen)

  Summary:
	Sends a data frame to the WiFi chip for transmission to the 802.11 network.

  Description:
    After the TCP/IP stack has created a data frame and called MACFlush() this
    function is called to notify the WiFi chip to transmit the data frame to the 
    802.11 network.  The actual data frame starts at index 4 in the allocated buffer.
    The first 4 bytes (indexes 0 - 3) were reserved, and this function fills them
    in with an internal preamble which notifies the WiFi chip that this is a data
    frame to send (as opposed to a management frame).

  Precondition:
	None

  Parameters:
	bufLen -- number of data bytes that comprise the data frame.
	             
  Returns:
  	None
  	
  Remarks:
	None
*****************************************************************************/
void SendRAWDataFrame(UINT16 bufLen)
{
    /* create internal preamble */
    UINT8 txDataPreamble[4] = { WF_DATA_REQUEST_TYPE, WF_STD_DATA_MSG_SUBTYPE, 1, 0};

    /* write out internal preamble, starting at index 0 in the raw window */
    RawWrite(RAW_DATA_TX_ID, 0, sizeof(txDataPreamble), txDataPreamble);

    /* Notify WiFi device that there is a transmit frame to send .  The frame will */
    /* be automatically deallocated after RF transmission is completed.            */
    RawMove(RAW_DATA_TX_ID, RAW_MAC, FALSE, bufLen);
    
    /* this raw window is logically no longer mounted.  The WiFi chip will  */
    /* automatically deallocate after RF transmission.                      */
    SetRawWindowState(RAW_DATA_TX_ID, WF_RAW_UNMOUNTED);
}
Пример #18
0
/*
*********************************************************************************************************
*                                   ScratchUnmount()
*
* Description : Unmounts Scratch from the specified RAW window.
*
* Argument(s) : rawId -- RAW window ID that scratch had been mounted to.
*
* Return(s)   : None
*
* Caller(s)   : WF Driver
*
* Notes:      : None
*
*********************************************************************************************************
*/
void ScratchUnmount(uint8_t rawId)
{
    RawMove(rawId, RAW_SCRATCH_POOL, false, 0);

    SetRawWindowState(rawId, WF_RAW_UNMOUNTED);

//    if (rawId == RAW_RX_ID)
//    {
//        SetRawWindowState(RAW_RX_ID, WF_RAW_UNMOUNTED);
//    }
//    else
//    {
//        SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
//    }

}
Пример #19
0
/* transmits raw Tx data frame to 802.11 network */
void RawSendTxBuffer(UINT16 len)
{
    RawMove(RAW_DATA_TX_ID, RAW_MAC, FALSE, len);
    SetRawWindowState(RAW_DATA_TX_ID, WF_RAW_UNMOUNTED);
} 
Пример #20
0
void DeallocateDataTxBuffer(void)
{
    RawMove(RAW_DATA_TX_ID, RAW_DATA_POOL, FALSE, 0);
    SetRawWindowState(RAW_DATA_TX_ID, WF_RAW_UNMOUNTED);
}  
Пример #21
0
/*****************************************************************************
 * FUNCTION: WaitForMgmtResponse
 *
 * RETURNS:  None
 *
 * PARAMS:   expectedSubtype -- The expected subtype of the mgmt response
 *           freeAction      -- FREE_MGMT_BUFFER or DO_NOT_FREE_MGMT_BUFFER
 *
 *  NOTES:   Called after sending a mgmt request.  This function waits for a mgmt
 *           response.  The caller can optionally request the the management 
 *           response be freed immediately (by this function) or not freed.  If not
 *           freed the caller is responsible to free the response buffer.
 *****************************************************************************/
void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction)
{
    #if defined(__18CXX)
        static tMgmtMsgRxHdr  hdr; 
    #else
        tMgmtMsgRxHdr  hdr; 
    #endif
    
    g_WaitingForMgmtResponse = TRUE;
        
    /* Wait until mgmt response is received */
    while (gMgmtConfirmMsgReceived == FALSE)
    {
        WFProcess();
        
        /* if received a data packet while waiting for mgmt packet */
        if (g_HostRAWDataPacketReceived)
        {
            // We can't let the StackTask processs data messages that come in while waiting for mgmt 
            // response because the application might send another mgmt message, which is illegal until the response
            // is received for the first mgmt msg.  And, we can't prevent the race condition where a data message 
            // comes in before a mgmt response is received.  Thus, the only solution is to throw away a data message
            // that comes in while waiting for a mgmt response.  This should happen very infrequently.  If using TCP then the 
            // stack takes care of retries.  If using UDP, the application has to deal with occasional data messages not being
            // received.  Also, applications typically do not send a lot of management messages after connected.

            // throw away the data rx 
            RawMountRxBuffer();
            DeallocateDataRxBuffer();
            g_HostRAWDataPacketReceived = FALSE;

            /* ensure interrupts enabled */
            WF_EintEnable();
        }    
    } 
    
    /* set this back to FALSE so the next mgmt send won't think he has a response before one is received */
    gMgmtConfirmMsgReceived = FALSE;
    
    
    /* if the caller wants to delete the response immediately (doesn't need any data from it */
    if (freeAction == FREE_MGMT_BUFFER)
    {
        /* read and verify result before freeing up buffer to ensure our message send was successful */
        RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr);

        /* mgmt response subtype had better match subtype we were expecting */
        WF_ASSERT(hdr.subtype == expectedSubtype);

        if (hdr.result == WF_ERROR_DISCONNECT_FAILED 
            || hdr.result == WF_ERROR_NOT_CONNECTED) {
            #if defined(STACK_USE_UART)
                putrsUART("Disconnect failed. Disconnect is allowed only when module is in connected state\r\n");
            #endif
        } else if (hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR) {
            #if defined(STACK_USE_UART)
                putrsUART("No stored scan results\r\n");
            #endif
        } else {
            WF_ASSERT(hdr.result == WF_SUCCESS); 
        }

        /* free mgmt buffer */
        DeallocateMgmtRxBuffer();  
        
        /* if there was a mounted data packet prior to the mgmt tx/rx transaction, then restore it */
        if (RestoreRxData == TRUE)
        {
            RestoreRxData = FALSE;
            PopRawWindow(RAW_RX_ID);
            SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED); 
        }          
    }   
}  
Пример #22
0
void DeallocateDataTxBuffer(void)
{
    RawMove(RAW_TX_ID, RAW_DATA_POOL, false, 0);
    RawWindowReady[RAW_TX_ID] = false;
    SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED);
}