示例#1
0
文件: main.c 项目: DINKIN/bertos
/* Process that reads from the USB port and writes to the UART port */
static void NORETURN usb_serial_process(void)
{
	iptr_t type = proc_currentUserData();

	KFile *in_fd = (type == USB_TO_SERIAL) ? &usb_port.fd : &ser_port.fd;
	KFile *out_fd = (type == USB_TO_SERIAL) ? &ser_port.fd : &usb_port.fd;

	while (1)
	{
		int c;

		c = kfile_getc(in_fd);
		if (UNLIKELY(c == EOF))
		{
			kfile_clearerr(in_fd);
			continue;
		}
		kfile_putc(c, out_fd);

		/*
		 * Toggle the STAT LED when some data passes through the
		 * usb-seral link
		 */
		LED_TOGGLE();
	}
}
示例#2
0
/**
 * Receive the tag message from channel, and if
 * the tag is good put the converted string into given buffer.
 * The fuction return the len of found tag string, otherwise EOF.
 */
int keytag_recv(struct TagPacket *pkt, uint8_t *tag, size_t len)
{
    int c;

    /* Get all chars from buffer */
    while ((c = kfile_getc(pkt->tag)) != EOF)
    {
        /* Search for STX char in received chars */
        if (c == TAG_STX)
        {
            /* When STX is found a new packet begins */
            if (pkt->sync)
                LOG_WARN("TAG double sync!\n");
            keytag_clearPkt(pkt);
            pkt->sync = true;
        }
        else if (pkt->sync)
        {
            /* Check for end of packet */
            if (c == TAG_ETX)
            {
                /* Terminate the tag string */
                size_t tag_len = MIN(len, pkt->len);

                /* Save read tag */
                memcpy(tag, pkt->buf, tag_len);
                pkt->sync = false;
                return tag_len;
            }
            else
            {
                /* Check for buffer overflow */
                if (pkt->len >= CONFIG_TAG_MAX_LEN)
                {
                    LOG_ERR("TAG buffer overflow\n");
                    pkt->sync = false;
                }
                else
                {
                    /* Add every char after STX to tag reading buffer */
                    if (pkt->sync)
                    {
                        pkt->buf[pkt->len] = c;
                        pkt->len++;
                    }
                }
            }
        }
    }
    if (kfile_error(pkt->tag) != 0)
    {
        LOG_ERR("Error %04x\n", kfile_error(pkt->tag));
        kfile_clearerr(pkt->tag);
    }

    return EOF;
}
示例#3
0
/**
 * Discard input to resynchronize with remote end.
 *
 * Discard incoming data until the kfile_getc stops receiving
 * characters for at least \a delay milliseconds.
 *
 * \note If the timeout occur, we reset the error before to
 * quit.
 */
void kfile_resync(KFile *fd, mtime_t delay)
{
	ticks_t start_time = timer_clock();
	for(;;)
	{
		if(kfile_getc(fd) != EOF)
			start_time = timer_clock();

		if ((timer_clock() - start_time) > ms_to_ticks(delay))
		{
			kfile_clearerr(fd);
			break;
		}

	}
}
示例#4
0
文件: hadarp.c 项目: batt/StratoSpera
static void NORETURN hadarp_process(void)
{
	char buf[16];

	while (1)
	{
		if (sig_check(SIG_POLIFEMO))
			kfile_putc('@', &ser.fd);

		if (kfile_gets(&ser.fd, buf, sizeof(buf)) == EOF)
		{
			hadarp_cnt = -1;
			kfile_clearerr(&ser.fd);
			continue;
		}

		if (buf[0] == '\0')
		{
			/* Discard empty strings */
			continue;
		}


		char *endptr = buf;
		int hadarp_raw = strtol(buf, &endptr, 10);

		if (*endptr != '\0' || hadarp_raw > 10000 || hadarp_raw < 0)
			hadarp_cnt = -1;
		else
		{
			/* Compensate for geiger tube dead time */
			float cps = hadarp_raw / 60.0;
			hadarp_cnt = ABS(cps / (1.0 - (cps * 1.9e-4)) * 60.0 + 0.5);
		}
		LOG_INFO("HADARP cnt:%d\n", hadarp_cnt);
	}
}
示例#5
0
/**
 * Try to read a packet from the pocketBus.
 * \return true if a packet is received, false otherwise.
 */
bool pocketbus_recv(struct PocketBusCtx *ctx, struct PocketMsg *msg)
{
	int c;

	/* Process incoming characters until buffer is not empty */
	while ((c = kfile_getc(ctx->fd)) != EOF)
	{
		/* Look for STX char */
		if (c == POCKETBUS_STX && !ctx->escape)
		{
			/* When an STX is found, inconditionally start a new packet */
			if (ctx->sync)
				kprintf("pocketBus double sync!\n");

			ctx->sync = true;
			ctx->len = 0;
			rotating_init(&ctx->in_cks);
			continue;
		}

		if (ctx->sync)
		{
			/* Handle escape mode */
			if (c == POCKETBUS_ESC && !ctx->escape)
			{
				ctx->escape = true;
				continue;
			}

			/* Handle message end */
			if (c == POCKETBUS_ETX && !ctx->escape)
			{
				ctx->sync = false;

				/* Check minimum size */
				if (ctx->len < sizeof(PocketBusHdr) + sizeof(rotating_t))
				{
					kprintf("pocketBus short pkt!\n");
					continue;
				}

				/* Remove checksum bytes from packet len */
				ctx->len -= sizeof(rotating_t);

				/* Compute checksum */
				rotating_update(ctx->buf, ctx->len, &ctx->in_cks);
				uint8_t cks_h = *(ctx->buf + ctx->len);
				uint8_t cks_l = *(ctx->buf + ctx->len + 1);

				rotating_t recv_cks = (cks_h << 8) | cks_l;

				/* Checksum check */
				if (recv_cks == ctx->in_cks)
				{
					PocketBusHdr *hdr = (PocketBusHdr *)ctx;

					/* Check packet version */
					if (hdr->ver == POCKETBUS_VER)
					{
						/* Packet received, set msg fields */
						msg->payload = ctx->buf + sizeof(PocketBusHdr);
						msg->addr = be16_to_cpu(hdr->addr);
						msg->len = ctx->len - sizeof(PocketBusHdr);
						msg->ctx = ctx;
						return true;
					}
					else
					{
						kprintf("pocketBus version mismatch, here[%d], there[%d]\n", POCKETBUS_VER, hdr->ver);
						continue;
					}
				}
				else
				{
					kprintf("pocketBus cks error, here[%04X], there[%04X]\n", ctx->in_cks, recv_cks);
					continue;
				}

			}

			ctx->escape = false;

			/* Check buffer overflow: simply ignore
			   received data and go to unsynced state. */
			if (ctx->len >= CONFIG_POCKETBUS_BUFLEN)
			{
				kprintf("pocketBus buffer overflow\n");
				ctx->sync = false;
				continue;
			}

			/* Put received data in the buffer */
			ctx->buf[ctx->len] = c;
			ctx->len++;
		}
	}

	/*
	 * Check stream status.
	 */
	if (kfile_error(ctx->fd))
	{
		LOG_ERR("fd status[%04X]\n", kfile_error(ctx->fd));
		kfile_clearerr(ctx->fd);
	}

	return false;
}
示例#6
0
/**
 * \brief Receive a file using the XModem protocol.
 *
 * \param ch Channel to use for transfer
 * \param fd Destination file
 *
 * \note This function allocates a large amount of stack (\see XM_BUFSIZE).
 */
bool xmodem_recv(KFile *ch, KFile *fd)
{
    char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */
    int c, i, blocksize;
    int blocknr = 0, last_block_done = 0, retries = 0;
    char *buf;
    uint8_t checksum;
    uint16_t crc;
    bool purge = false;
    bool usecrc = true;


    LOG_INFO("Starting Transfer...\n");
    purge = true;
    kfile_clearerr(ch);

    /* Send initial NAK to start transmission */
    for(;;)
    {
        if (XMODEM_CHECK_ABORT)
        {
            kfile_putc(XM_CAN, ch);
            kfile_putc(XM_CAN, ch);
            LOG_INFO("Transfer aborted\n");
            return false;
        }

        /*
         * Discard incoming input until a timeout occurs, then send
         * a NAK to the transmitter.
         */
        if (purge)
        {
            purge = false;

            if (kfile_error(ch))
            {
                LOG_ERR("Retries %d\n", retries);
            }

            kfile_resync(ch, 200);
            retries++;

            if (retries >= CONFIG_XMODEM_MAXRETRIES)
            {
                kfile_putc(XM_CAN, ch);
                kfile_putc(XM_CAN, ch);
                LOG_INFO("Transfer aborted\n");
                return false;
            }

            /* Transmission start? */
            if (blocknr == 0)
            {
                if (retries < CONFIG_XMODEM_MAXCRCRETRIES)
                {
                    LOG_INFO("Request Tx (CRC)\n");
                    kfile_putc(XM_C, ch);
                }
                else
                {
                    /* Give up with CRC and fall back to checksum */
                    usecrc = false;
                    LOG_INFO("Request Tx (BCC)\n");
                    kfile_putc(XM_NAK, ch);
                }
            }
            else
                kfile_putc(XM_NAK, ch);
        }

        switch (kfile_getc(ch))
        {
#if XM_BUFSIZE >= 1024
        case XM_STX:  /* Start of header (1024-byte block) */
            blocksize = 1024;
            goto getblock;
#endif

        case XM_SOH:  /* Start of header (128-byte block) */
            blocksize = 128;
            /* Needed to avoid warning if XM_BUFSIZE < 1024 */

getblock:
            /* Get block number */
            c = kfile_getc(ch);

            /* Check complemented block number */
            if ((~c & 0xff) != kfile_getc(ch))
            {
                LOG_WARN("Bad blk (%d)\n", c);
                purge = true;
                break;
            }

            /* Determine which block is being sent */
            if (c == (blocknr & 0xff))
            {
                /* Last block repeated */
                LOG_INFO("Repeat blk %d\n", blocknr);
            }
            else if (c == ((blocknr + 1) & 0xff))
            {
                /* Next block */
                LOG_INFO("Recv blk %d\n", ++blocknr);
            }
            else
            {
                /* Sync lost */
                LOG_WARN("Sync lost (%d/%d)\n", c, blocknr);
                purge = true;
                break;
            }

            buf = block_buffer;	/* Reset pointer to start of buffer */
            checksum = 0;
            crc = 0;
            for (i = 0; i < blocksize; i++)
            {
                if ((c = kfile_getc(ch)) == EOF)
                {
                    purge = true;
                    break;
                }

                /* Store in buffer */
                *buf++ = (char)c;

                /* Calculate block checksum or CRC */
                if (usecrc)
                    crc = UPDCRC16(c, crc);
                else
                    checksum += (char)c;
            }

            if (purge)
                break;

            /* Get the checksum byte or the CRC-16 MSB */
            if ((c = kfile_getc(ch)) == EOF)
            {
                purge = true;
                break;
            }

            if (usecrc)
            {
                crc = UPDCRC16(c, crc);

                /* Get CRC-16 LSB */
                if ((c = kfile_getc(ch)) == EOF)
                {
                    purge = true;
                    break;
                }

                crc = UPDCRC16(c, crc);

                if (crc)
                {
                    LOG_ERR("Bad CRC: %04x\n", crc);
                    purge = true;
                    break;
                }
            }
            /* Compare the checksum */
            else if (c != checksum)
            {
                LOG_ERR("Bad sum: %04x/%04x\n", checksum, c);
                purge = true;
                break;
            }

            /*
             * Avoid flushing the same block twice.
             * This could happen when the sender does not receive our
             * acknowledge and resends the same block.
             */
            if (last_block_done < blocknr)
            {
                /* Call user function to flush the buffer */
                if (kfile_write(fd, block_buffer, blocksize))
                {
                    /* Acknowledge block and clear error counter */
                    kfile_putc(XM_ACK, ch);
                    retries = 0;
                    last_block_done = blocknr;
                }
                else
                {
                    /* User callback failed: abort transfer immediately */
                    retries = CONFIG_XMODEM_MAXRETRIES;
                    purge = true;
                }
            }
            break;

        case XM_EOT:	/* End of transmission */
            kfile_putc(XM_ACK, ch);
            LOG_INFO("Transfer completed\n");
            return true;

        case EOF: /* Timeout or serial error */
            purge = true;
            break;

        default:
            LOG_INFO("Skipping garbage\n");
            purge = true;
            break;
        }
    } /* End forever */
}
示例#7
0
/**
 * \brief Transmit some data using the XModem protocol.
 *
 * \param ch Channel to use for transfer
 * \param fd Source file
 *
 * \note This function allocates a large amount of stack for
 *       the XModem transfer buffer (\see XM_BUFSIZE).
 */
bool xmodem_send(KFile *ch, KFile *fd)
{
    char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */
    size_t size = -1;
    int blocknr = 1, retries = 0, c, i;
    bool proceed, usecrc = false;
    uint16_t crc;
    uint8_t sum;

    /*
     * Reading a block can be very slow, so we read the first block early
     * to avoid receiving double XM_C char.
     * This could happen if we check for XM_C and then read the block, giving
     * the receiving device time to send another XM_C char misinterpretating
     * the blocks sent.
     */
    size = kfile_read(fd, block_buffer, XM_BUFSIZE);

    kfile_clearerr(ch);
    LOG_INFO("Wait remote host\n");

    for(;;)
    {
        proceed = false;
        do
        {
            if (XMODEM_CHECK_ABORT)
                return false;

            switch (c = kfile_getc(ch))
            {
            case XM_NAK:
                LOG_INFO("Resend blk %d\n", blocknr);
                proceed = true;
                break;

            case XM_C:
                if (c == XM_C)
                {
                    LOG_INFO("Tx start (CRC)\n");
                    usecrc = true;
                }
                else
                {
                    LOG_INFO("Tx start (BCC)\n");
                }

                proceed = true;
                break;

            case XM_ACK:
                /* End of transfer? */
                if (!size)
                    return true;

                /* Call user function to read in one block */
                size = kfile_read(fd, block_buffer, XM_BUFSIZE);
                LOG_INFO("Send blk %d\n", blocknr);
                blocknr++;
                retries = 0;
                proceed = true;
                break;

            case EOF:
                kfile_clearerr(ch);
                retries++;
                LOG_INFO("Retries %d\n", retries);
                if (retries <= CONFIG_XMODEM_MAXRETRIES)
                    break;
            /* falling through! */

            case XM_CAN:
                LOG_INFO("Transfer aborted\n");
                return false;

            default:
                LOG_INFO("Skipping garbage\n");
                break;
            }
        }
        while (!proceed);

        if (!size)
        {
            kfile_putc(XM_EOT, ch);
            continue;
        }

        /* Pad block with 0xFF if it's partially full */
        memset(block_buffer + size, 0xFF, XM_BUFSIZE - size);

        /* Send block header (STX, blocknr, ~blocknr) */
#if XM_BUFSIZE == 128
        kfile_putc(XM_SOH, ch);
#else
        kfile_putc(XM_STX, ch);
#endif
        kfile_putc(blocknr & 0xFF, ch);
        kfile_putc(~blocknr & 0xFF, ch);

        /* Send block and compute its CRC/checksum */
        sum = 0;
        crc = 0;
        for (i = 0; i < XM_BUFSIZE; i++)
        {
            kfile_putc(block_buffer[i], ch);
            crc = UPDCRC16(block_buffer[i], crc);
            sum += block_buffer[i];
        }

        /* Send CRC/Checksum */
        if (usecrc)
        {
            kfile_putc(crc >> 8, ch);
            kfile_putc(crc & 0xFF, ch);
        }
        else
            kfile_putc(sum, ch);
    }
示例#8
0
文件: protocol.c 项目: mtarek/BeRTOS
void protocol_run(KFile *fd)
{
	/**
	 * \todo to be removed, we could probably access the serial FIFO
	 * directly
	 */
	static char linebuf[80];

	if (!interactive)
	{
		kfile_gets(fd, linebuf, sizeof(linebuf));

		// reset serial port error anyway
		kfile_clearerr(fd);

		// check message minimum length
		if (linebuf[0])
		{
			/* If we enter lines beginning with sharp(#)
			they are stripped out from commands */
			if(linebuf[0] != '#')
			{
				if (linebuf[0] == 0x1B && linebuf[1] == 0x1B)  // ESC
				{
					interactive = true;
					kfile_printf(fd, "Entering interactive mode\r\n");
				}
				else
				{
					protocol_parse(fd, linebuf);
				}
			}
		}
	}
	else
	{
		const char *buf;

		/*
		 * Read a line from serial. We use a temporary buffer
		 * because otherwise we would have to extract a message
		 * from the port immediately: there might not be any
		 * available, and one might get free while we read
		 * the line. We also add a fake ID at the start to
		 * fool the parser.
		 */
		buf = rl_readline(&rl_ctx);

		/* If we enter lines beginning with sharp(#)
		they are stripped out from commands */
		if(buf && buf[0] != '#')
		{
			if (buf[0] != '\0')
			{
				// exit special case to immediately change serial input
				if (!strcmp(buf, "exit") || !strcmp(buf, "quit"))
				{
					rl_clear_history(&rl_ctx);
					kfile_printf(fd, "Leaving interactive mode...\r\n");
					interactive = FORCE_INTERACTIVE;
				}
				else
				{
					//TODO: remove sequence numbers
					linebuf[0] = '0';
					linebuf[1] = ' ';

					strncpy(linebuf + 2, buf, sizeof(linebuf) - 3);
					linebuf[sizeof(linebuf) - 1] = '\0';
					protocol_parse(fd, linebuf);
				}
			}
		}
	}
}