예제 #1
0
static void retry_transmit(struct r3964_info *pInfo)
{
   if(pInfo->nRetry<R3964_MAX_RETRIES)
   {
      TRACE_PE("transmission failed. Retry #%d", 
             pInfo->nRetry);
      pInfo->bcc = 0;
      put_char(pInfo, STX);
      flush(pInfo);
      pInfo->state = R3964_TX_REQUEST;
      pInfo->count_down = R3964_TO_QVZ;
      pInfo->nRetry++;
   }
   else
   {
      TRACE_PE("transmission failed after %d retries", 
             R3964_MAX_RETRIES);

      remove_from_tx_queue(pInfo, R3964_TX_FAIL);
      
      put_char(pInfo, NAK);
      flush(pInfo);
      pInfo->state = R3964_IDLE;

      trigger_transmit(pInfo);
   }
}
예제 #2
0
static void receive_char(struct r3964_info *pInfo, const unsigned char c)
{
	switch (pInfo->state) {
	case R3964_TX_REQUEST:
		if (c == DLE) {
			TRACE_PS("TX_REQUEST - got DLE");

			pInfo->state = R3964_TRANSMITTING;
			pInfo->tx_position = 0;

			transmit_block(pInfo);
		} else if (c == STX) {
			if (pInfo->nRetry == 0) {
				TRACE_PE("TX_REQUEST - init conflict");
				if (pInfo->priority == R3964_SLAVE) {
					goto start_receiving;
				}
			} else {
				TRACE_PE("TX_REQUEST - secondary init "
					"conflict!? Switching to SLAVE mode "
					"for next rx.");
				goto start_receiving;
			}
		} else {
			TRACE_PE("TX_REQUEST - char != DLE: %x", c);
			retry_transmit(pInfo);
		}
		break;
	case R3964_TRANSMITTING:
		if (c == NAK) {
			TRACE_PE("TRANSMITTING - got NAK");
			retry_transmit(pInfo);
		} else {
			TRACE_PE("TRANSMITTING - got invalid char");

			pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
		}
		break;
	case R3964_WAIT_FOR_TX_ACK:
		if (c == DLE) {
			TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
			remove_from_tx_queue(pInfo, R3964_OK);

			pInfo->state = R3964_IDLE;
			trigger_transmit(pInfo);
		} else {
			retry_transmit(pInfo);
		}
		break;
	case R3964_WAIT_FOR_RX_REPEAT:
		/* FALLTROUGH */
	case R3964_IDLE:
		if (c == STX) {
			/* Prevent rx_queue from overflow: */
			if (pInfo->blocks_in_rx_queue >=
			    R3964_MAX_BLOCKS_IN_RX_QUEUE) {
				TRACE_PE("IDLE - got STX but no space in "
						"rx_queue!");
				pInfo->state = R3964_WAIT_FOR_RX_BUF;
				mod_timer(&pInfo->tmr,
					  jiffies + R3964_TO_NO_BUF);
				break;
			}
start_receiving:
			/* Ok, start receiving: */
			TRACE_PS("IDLE - got STX");
			pInfo->rx_position = 0;
			pInfo->last_rx = 0;
			pInfo->flags &= ~R3964_ERROR;
			pInfo->state = R3964_RECEIVING;
			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
			pInfo->nRetry = 0;
			put_char(pInfo, DLE);
			flush(pInfo);
			pInfo->bcc = 0;
		}
		break;
	case R3964_RECEIVING:
		if (pInfo->rx_position < RX_BUF_SIZE) {
			pInfo->bcc ^= c;

			if (c == DLE) {
				if (pInfo->last_rx == DLE) {
					pInfo->last_rx = 0;
					goto char_to_buf;
				}
				pInfo->last_rx = DLE;
				break;
			} else if ((c == ETX) && (pInfo->last_rx == DLE)) {
				if (pInfo->flags & R3964_BCC) {
					pInfo->state = R3964_WAIT_FOR_BCC;
					mod_timer(&pInfo->tmr,
						  jiffies + R3964_TO_ZVZ);
				} else {
					on_receive_block(pInfo);
				}
			} else {
				pInfo->last_rx = c;
char_to_buf:
				pInfo->rx_buf[pInfo->rx_position++] = c;
				mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
			}
		}
		/* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
		break;
	case R3964_WAIT_FOR_BCC:
		pInfo->last_rx = c;
		on_receive_block(pInfo);
		break;
	}
}