Example #1
0
/**
 * flash25 init function.
 * This function init a comunication channel and
 * try to read manufacturer id of serial memory,
 * then check if is equal to selected type.
 */
static bool flash25_pin_init(Flash25 *fd)
{
	uint8_t device_id;
	uint8_t manufacturer;

	SPI_HW_INIT();

	SS_ACTIVE();
	/*
	 * Send read id productor opcode on
	 * comunication channel
	 * TODO:controllare se ha senso
	 */
	kfile_putc(FLASH25_RDID, fd->channel);

	manufacturer = kfile_getc(fd->channel);
	device_id = kfile_getc(fd->channel);

	SS_INACTIVE();

	if((FLASH25_MANUFACTURER_ID == manufacturer) &&
		(FLASH25_DEVICE_ID == device_id))
		return true;
	else
		return false;
}
Example #2
0
File: main.c Project: 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();
	}
}
Example #3
0
/**
 * Read a line long at most as size and put it
 * in buf, with optional echo.
 *
 * \return number of chars read, or EOF in case
 *         of error.
 */
int kfile_gets_echo(struct KFile *fd, char *buf, int size, bool echo)
{
	int i = 0;
	int c;

	for (;;)
	{
		if ((c = kfile_getc(fd)) == EOF)
		{
			buf[i] = '\0';
			return -1;
		}

		/* FIXME */
		if (c == '\r' || c == '\n' || i >= size-1)
		{
			buf[i] = '\0';
			if (echo)
				kfile_print(fd, "\r\n");
			break;
		}
		buf[i++] = c;
		if (echo)
			kfile_putc(c, fd);
	}

	return i;
}
Example #4
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;
}
Example #5
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;
		}

	}
}
Example #6
0
int8_t gsmSMSSend(const char *number, const char *message)
{
	int8_t resp, i;
	char buff[32];

	gsmDebug("Sending SMS\n");
#if 0
	if (strlen(message)>160)
		message[160] = 0;
#else
#warning CHECK for message max length!!!
#endif
	// Sending destination number
	sprintf(buff, "AT+CMGS=\"%s\", 145", number);
	_gsmWriteLine(buff);
	DELAY(1000);
	//_gsmWrite("AT+CMGS=\"", 9);
	//_gsmWrite(number, strlen(number));
	//_gsmWriteLine("\", 145");

	// Wait for modem message prompt
	//_gsmRead(buff, 32);
	for (i=0; i<15; i++) {
		(*buff) = kfile_getc(&(gsm->fd));
		if ((*buff) == EOF)
			return -1;
		if ((*buff) == '>')
			break;
	}
	if (i == 15)
		return -1;

	// Sending message
	_gsmWriteLine(message);
	DELAY(1000);

	// Sending terminator
	_gsmWriteLine("\x1a");

	// Waiting send confirmation
	_gsmRead(buff, 32);
	resp = _gsmReadResult();

	return resp;
}
Example #7
0
/**
 * Wait until flash memory is ready.
 */
static void flash25_waitReady(Flash25 *fd)
{
	uint8_t stat;

	while (1)
	{
		SS_ACTIVE();

		kfile_putc(FLASH25_RDSR, fd->channel);
		stat = kfile_getc(fd->channel);

		SS_INACTIVE();

		if (!(stat & RDY_BIT))
			break;

		cpu_relax();
	}
}
Example #8
0
////////////////////////////////////////////////////////////
// The Poll function reads data from the modem, handles   //
// frame recognition and passes data on to higher layers  //
// if valid packets are found                             //
////////////////////////////////////////////////////////////
void mp1Poll(MP1 *mp1) {
	int byte; // A place to store our read byte

	// Read bytes from the modem until we reach EOF
	while ((byte = kfile_getc(mp1->modem)) != EOF) {
		// We read something from the modem, so we
		// set the settleTimer
		mp1->settleTimer = timer_clock();

		/////////////////////////////////////////////
		// This following block handles forward    //
		// error correction using an interleaved   //
		// (12,8) Hamming code                     //
		/////////////////////////////////////////////

		// If we have started reading (received an
		// HDLC_FLAG), we will start looking at the
		// incoming data and perform forward error
		// correction on it.
		

		if ((mp1->reading && (byte != AX25_ESC )) || (mp1->reading && (mp1->escape && (byte == AX25_ESC || byte == HDLC_FLAG || byte == HDLC_RESET)))) {
			// We have a byte, increment our read counter
			mp1->readLength++;

			// Check if we have read three bytes. If we
			// have, we should now have a block of two
			// data bytes and a parity byte. This block
			if (mp1->readLength % MP1_INTERLEAVE_SIZE == 0) {
				// If the last character in the block
				// looks like a control character, we
				// need to set the escape indicator to
				// false, since the next byte will be
				// read immediately after the FEC
				// routine, and thus, the normal reading
				// code will not reset the indicator.
				if (byte == AX25_ESC || byte == HDLC_FLAG || byte == HDLC_RESET) mp1->escape = false;
				
				// The block is interleaved, so we will
				// first put the received bytes in the
				// deinterleaving buffer
				for (int i = 1; i < MP1_INTERLEAVE_SIZE; i++) {
					mp1->interleaveIn[i-1] = mp1->buffer[mp1->packetLength-(MP1_INTERLEAVE_SIZE-i)];
				}
				mp1->interleaveIn[MP1_INTERLEAVE_SIZE-1] = byte;

				// We then deinterleave the block
				mp1Deinterleave(mp1);

				// Adjust the packet length, since we will get
				// parity bytes in the data buffer with block
				// sizes larger than 3
				mp1->packetLength -= MP1_INTERLEAVE_SIZE/3 - 1;

				// For each 3-byte block in the deinterleaved
				// bytes, we apply forward error correction
				for (int i = 0; i < MP1_INTERLEAVE_SIZE; i+=3) {
					// We now calculate a parity byte on the
					// received data.

					// Deinterleaved data bytes
					uint8_t a = mp1->interleaveIn[i];
					uint8_t b = mp1->interleaveIn[i+1];

					// Deinterleaved parity byte
					uint8_t p = mp1->interleaveIn[i+2];

					mp1->calculatedParity = mp1ParityBlock(a, b);

					// By XORing the calculated parity byte
					// with the received parity byte, we get
					// what is called the "syndrome". This
					// number will tell us if we had any
					// errors during transmission, and if so
					// where they are. Using Hamming code, we
					// can only detect single bit errors in a
					// byte though, which is why we interleave
					// the data, since most errors will usually
					// occur in bursts of more than one bit.
					// With 2 data byte interleaving we can
					// correct 2 consecutive bit errors.
					uint8_t syndrome = mp1->calculatedParity ^ p;
					if (syndrome == 0x00) {
						// If the syndrome equals 0, we either
						// don't have any errors, or the error
						// is unrecoverable, so we don't do
						// anything
					} else {
						// If the syndrome is not equal to 0,
						// there is a problem, and we will try
						// to correct it. We first need to split
						// the syndrome byte up into the two
						// actual syndrome numbers, one for
						// each data byte.
						uint8_t syndromes[2];
						syndromes[0] = syndrome & 0x0f;
						syndromes[1] = (syndrome & 0xf0) >> 4;

						// Then we look at each syndrome number
						// to determine what bit in the data
						// bytes to correct.
						for (int i = 0; i < 2; i++) {
							uint8_t s = syndromes[i];
							uint8_t correction = 0x00;
							if (s == 1 || s == 2 || s == 4 || s == 8) {
								// This signifies an error in the
								// parity block, so we actually
								// don't need any correction
								continue;
							}

							// The following determines what
							// bit to correct according to
							// the syndrome value.
							if (s == 3)  correction = 0x01;
							if (s == 5)  correction = 0x02;
							if (s == 6)  correction = 0x04;
							if (s == 7)  correction = 0x08;
							if (s == 9)  correction = 0x10;
							if (s == 10) correction = 0x20;
							if (s == 11) correction = 0x40;
							if (s == 12) correction = 0x80;

							// And finally we apply the correction
							if (i == 1) a ^= correction;
							if (i == 0) b ^= correction;

							// This is just for testing purposes.
							// Nice to know when corrections were
							// actually made.
							if (s != 0) mp1->correctionsMade += 1;
						}
					}

					// We now update the checksum of the packet
					// with the deinterleaved and possibly
					// corrected bytes.
					mp1->checksum_in ^= a;
					mp1->checksum_in ^= b;
					mp1->buffer[mp1->packetLength-(MP1_DATA_BLOCK_SIZE)+((i/3)*2)] = a;
					mp1->buffer[mp1->packetLength-(MP1_DATA_BLOCK_SIZE-1)+((i/3)*2)] = b;
				}

				continue;
			}
		}
		/////////////////////////////////////////////
		// End of forward error correction block   //
		/////////////////////////////////////////////
		
		// This next part of the poll function handles
		// the reading from the modem, and looks for
		// starts and ends of transmissions. It also
		// handles escape characters by discarding them
		// so they don't get put into the output data.

		// Let's first check if we have read an HDLC_FLAG.
		if (!mp1->escape && byte == HDLC_FLAG) {
			// We are not in an escape sequence and we
			// found a HDLC_FLAG. This can mean two things:
			if (mp1->readLength >= MP1_MIN_FRAME_LENGTH) {
				// We already have more data than the minimum
				// frame length, which means the flag signifies
				// the end of the packet. Pass control to the
				// decoder.
				//
				// We also set the settle timer to indicate
				// the time the frame completed reading.
				mp1->settleTimer = timer_clock();
				if ((mp1->checksum_in & 0xff) == 0x00) {
					if (SERIAL_DEBUG) kprintf("[CHK-OK] [C=%d] ", mp1->correctionsMade);
					mp1Decode(mp1);
				} else {
					// Checksum was incorrect, we don't do anything,
					// but you can enable the decode anyway, if you
					// need it for testing or debugging
					if (PASSALL) {
						if (SERIAL_DEBUG) kprintf("[CHK-ER] [C=%d] ", mp1->correctionsMade);
						mp1Decode(mp1);
					}
				}
			}
			// If the above is not the case, this must be the
			// beginning of a frame
			mp1->reading = true;
			mp1->packetLength = 0;
			mp1->readLength = 0;
			mp1->checksum_in = MP1_CHECKSUM_INIT;
			mp1->correctionsMade = 0;

			// We have indicated that we are reading,
			// and reset the length counter. Now we'll
			// continue to the next byte.
			continue;
		}

		if (!mp1->escape && byte == HDLC_RESET) {
			// Not good, we got a reset. The transmitting
			// party may have encountered an error. We'll
			// stop receiving this packet immediately.
			mp1->reading = false;
			continue;
		}

		if (!mp1->escape && byte == AX25_ESC) {
			// We found an escape character. We'll set
			// the escape seqeunce indicator so we don't
			// interpret the next byte as a reset or flag
			mp1->escape = true;

			// We then continue reading the next byte.
			continue;
		}

		// Now let's get to the actual reading of the data
		if (mp1->reading) {
			if (mp1->packetLength < MP1_MAX_FRAME_LENGTH + MP1_INTERLEAVE_SIZE) {
				// If the length of the current incoming frame is
				// still less than our max length, put the incoming
				// byte in the buffer. When we have collected 3
				// bytes, they will be processed by the error
				// correction part above.
				mp1->buffer[mp1->packetLength++] = byte;
			} else {
				// If not, we have a problem: The buffer has overrun
				// We need to stop receiving, and the packet will be
				// dropped :(
				mp1->reading = false;
			}
		}

		// We need to set the escape sequence indicator back
		// to false after each byte.
		mp1->escape = false;
	}
Example #9
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;
}
Example #10
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 */
}
Example #11
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);
    }
Example #12
0
/**
 * @return 1 if a valid message has been retrived, 0 on no valid message, -1
 * on parsing error.
 */
int8_t gsmSMSByIndex(gsmSMSMessage_t * msg, uint8_t index) {
	char c;
	uint8_t i;
	char buff[13];
	char *text;

	// SMS indexes are 1..10
	if (!index || index>10)
		return 0;

	// Get the SMS message by the specified index
	sprintf(buff, "AT+CMGR=%d", index);
	_gsmWriteLine(buff);
	// Example responce:
	// +CMGR: "REC READ","+393357963938","","10/12/14,22:59:15+04"<0D><0A>
	// $NUM+393473153808$NUM+3355763944$RES$MSG:PiazzaleLargo e Lungo, Milano, Italy$12345<0D>
	// <0D><0A>
	// <0D><0A>
	// 0<0D>

	//***** Reading message Type, record format:
	// +CMGR: <TYPE>
	// wherem TYPE is:
	// Type          Bytes  Description
	// "REC UNREAD"     12  Received unread messages
	// "REC READ"       10  Received read messages
	// "STO UNSENT"     12  Stored unsent messages
	// "STO SENT"       10  Stored sent messages
	// Minimum unique substring: 6 Bytes
	// Thus, to parse the actual type, we read:
	//     "+CMGR: " + 6Bytes = 13Bytes


	// Check if this message index is empty
	// In this case it is returned just "0<0D>"
	c = kfile_getc(&(gsm->fd));
	if (c == EOF)
		goto parse_error;
	if (c == '0') {
		msg->from[0] = 0;
		msg->time[0] = 0;
		msg->text[0] = 0;
		LOG_INFO("SMS, P: %d, EMPTY\n", index);
		return 0;
	}

	// Read the rest of the initial record identifier
	if (!kfile_read(&(gsm->fd), buff, 12))
		goto parse_error;

	// TODO: Parse message type
	//

	//***** Sender number
	// Scanning for second '"', than parse the sender number
	for (i=2; i; ) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			i--;
	}
	// Save the sender number, till next '"'
	for (i=0; i<15; i++) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			break;
		msg->from[i] = c;
	}
	msg->from[i] = '\0';

	//***** Timestamp parsing
	// Scanning for three '"', than parse the timestamp
	for (i=3; i; ) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			i--;
	}
	// Save the timestamp (20 Bytes + terminator)
	if (!kfile_read(&(gsm->fd), msg->time, 20))
		goto parse_error;
	msg->time[20] = '\0';
	// Discard remaining chars till line termination ["<0D><0A>]
	if (!kfile_read(&(gsm->fd), buff, 3))
		goto parse_error;

	//***** Message parsing
	text = msg->text;
	(*text) = kfile_getc(&(gsm->fd));
	if ((*text) == EOF)
		goto parse_error;

	if ((*text) == '$') {
		// Scanning for first ':', than parse the message
		for (i=0; i<64; i++) {
			c = kfile_getc(&(gsm->fd));
			if (c == EOF)
				goto parse_error;
			if (c==':')
				break;
		}
		// Save the message
		if (_gsmRead(text, 160) == -1)
			goto parse_error;
	} else {
		// We are already at the beginning of the message,
		// save the remainder of the text
		if (_gsmRead(text+1, 159) == -1)
			goto parse_error;
	}

	LOG_INFO("SMS, P: %d, T: %s, N: %s, M: %s\n",
			index, msg->time, msg->from, msg->text);

	return 1;

parse_error:
	gsmDebug("Parse FAILED\n");
	return -1;
}