/// <summary> /// Parses data read from the SD in STANDBY mode and inserts it into the queue /// of responses. /// </summary> /// <remarks> /// This function takes advantage of the fact that a result response /// from the SD for an AT command has a unique exact length among all other /// possible AT command responses. /// </remarks> private void Parse() { byte[] delim = (byte[])s_Cmds[c_ATR_DELIMETER]; // Extract responses and put them in the response queue bool foundResponse = false; int startIndex = 0; int closeIndex = 0; while (0 <= (startIndex = BytesIndexOf(m_readBuffer, startIndex, m_bytesInRead, delim))) { // Find closing delimeter closeIndex = BytesIndexOf(m_readBuffer, startIndex + 1, m_bytesInRead, delim); if (-1 == closeIndex) break; foundResponse = true; SDResponse response = new SDResponse(); // Check for result response int len = closeIndex + delim.Length - startIndex; response.Data = null; if (((byte[])s_Cmds[c_ATR_OK]).Length == len) { response.Type = c_ATR_OK; } else if (((byte[])s_Cmds[c_ATR_ERROR]).Length == len) { response.Type = c_ATR_ERROR; } else if (((byte[])s_Cmds[c_ATR_DISCONNECT]).Length == len) { response.Type = c_ATR_DISCONNECT; } else if (BytesEqual(m_readBuffer, startIndex, (byte[])s_Cmds[c_ATR_CONNECT], 0, ((byte[])s_Cmds[c_ATR_CONNECT]).Length)) { response.Type = c_ATR_CONNECT; SDResponse addrResponse = new SDResponse(); addrResponse.Type = -1; addrResponse.Data = new byte[len - ((byte[])s_Cmds[c_ATR_CONNECT]).Length]; Array.Copy(m_readBuffer, ((byte[])s_Cmds[c_ATR_CONNECT]).Length, addrResponse.Data, 0, addrResponse.Data.Length); m_responseQueue.Add(addrResponse); } else { response.Type = -1; response.Data = new byte[len]; Array.Copy(m_readBuffer, startIndex, response.Data, 0, len); } m_responseQueue.Add(response); startIndex = closeIndex + 1; } if (foundResponse) { // Move all remaining bytes to the front of the read buffer int lastIndex = (0 > startIndex) ? closeIndex + delim.Length : startIndex; m_bytesInRead = m_bytesInRead - lastIndex; if (0 < m_bytesInRead) { Array.Copy(m_readBuffer, lastIndex, m_readBuffer, 0, m_bytesInRead); } } }
/// <summary> /// An online read; reads up to len bytes from the SD into the given buffer /// and stops if the given timeout expires. In the case of a disconnect, /// reads up to len chars and returns them, if that's not possible then /// returns up to the "\r\nDISCONNECT\r\n" message and indicates disconnect /// by returning -1. Sets buffer to empty if no data could be read. /// </summary> /// <param name="buf"> /// The buffer to read into /// </param> /// <param name="to"> /// The max amount of time to read /// </param> /// <returns> /// The number of bytes read, or -1 on disconnect /// </returns> internal int Read(ref byte[] buf, int to) { // Check for a disconnect if (0 < m_responseQueue.Count) return -1; // Take bytes from the read buffer if there are any int bytesRead = 0; int bytesToRead = buf.Length; if (0 < m_bytesInRead) { bytesRead = (m_bytesInRead >= bytesToRead) ? bytesToRead : m_bytesInRead; Array.Copy(m_readBuffer, buf, bytesRead); m_bytesInRead -= bytesRead; bytesToRead -= bytesRead; if (0 < m_bytesInRead) Array.Copy(m_readBuffer, bytesRead, m_readBuffer, 0, m_bytesInRead); } // Read from SerialStream if there is more to read if (0 < bytesToRead) bytesRead += m_stream.Read(buf, bytesRead, bytesToRead, to); // Check for "\r\nDISCONNECT\r\n" in newly read bytes byte[] bytes_CR = new byte[] { c_CR }; byte[] disconnect = ((byte[])s_Cmds[c_ATR_DISCONNECT]); if (disconnect.Length > m_bytesInRead) { // Search for the beginning of "\r\nDISCONNECT\r\n" in buf int prefixIndex = (0 < bytesRead - disconnect.Length) ? bytesRead - disconnect.Length : 0; prefixIndex = BytesIndexOf(buf, prefixIndex, bytesRead, bytes_CR); if (0 <= prefixIndex) { // Read more if not enough bytes to check for "\r\nDISCONNECT\r\n" int endLen = bytesRead - prefixIndex + m_bytesInRead; if (endLen < disconnect.Length) { int num = m_stream.Read(m_readBuffer, m_bytesInRead, disconnect.Length - endLen, c_DefaultReadTimeout); m_bytesInRead += num; if (disconnect.Length - endLen != num) return bytesRead; } // Check if last read bytes are equal to "\r\nDISCONNECT\r\n" if (BytesEqual(buf, prefixIndex, disconnect, 0, bytesRead - prefixIndex) && BytesEqual(m_readBuffer, 0, disconnect, bytesRead - prefixIndex, disconnect.Length - (bytesRead - prefixIndex)) ) { // Then remove the "\r\nDISCONNECT\r\n" prefix from buf bytesRead -= bytesRead - prefixIndex; bytesRead = (bytesRead == 0) ? -1 : bytesRead; SDResponse dResponse = new SDResponse(); dResponse.Type = c_ATR_DISCONNECT; dResponse.Data = null; m_responseQueue.Add(dResponse); } } } return bytesRead; }