Ejemplo n.º 1
0
/*
 * queue a received (usb-)packet for later processing
 */
static int pkt_add(struct garmin_data *garmin_data_p,
		   unsigned char *data, unsigned int data_length)
{
	int state = 0;
	int result = 0;
	unsigned long flags;
	struct garmin_packet *pkt;

	/* process only packets containg data ... */
	if (data_length) {
		pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
								GFP_ATOMIC);
		if (pkt == NULL) {
			dev_err(&garmin_data_p->port->dev, "out of memory\n");
			return 0;
		}
		pkt->size = data_length;
		memcpy(pkt->data, data, data_length);

		spin_lock_irqsave(&garmin_data_p->lock, flags);
		garmin_data_p->flags |= FLAGS_QUEUING;
		result = list_empty(&garmin_data_p->pktlist);
		pkt->seq = garmin_data_p->seq_counter++;
		list_add_tail(&pkt->list, &garmin_data_p->pktlist);
		state = garmin_data_p->state;
		spin_unlock_irqrestore(&garmin_data_p->lock, flags);

		dev_dbg(&garmin_data_p->port->dev,
			"%s - added: pkt: %d - %d bytes\n", __func__,
			pkt->seq, data_length);

		/* in serial mode, if someone is waiting for data from
		   the device, convert and send the next packet to tty. */
		if (result && (state == STATE_GSP_WAIT_DATA))
			gsp_next_packet(garmin_data_p);
	}
	return result;
}
Ejemplo n.º 2
0
static int gsp_receive(struct garmin_data *garmin_data_p,
		       const unsigned char *buf, int count)
{
	unsigned long flags;
	int offs = 0;
	int ack_or_nak_seen = 0;
	__u8 *dest;
	int size;
	/* dleSeen: set if last byte read was a DLE */
	int dleSeen;
	/* skip: if set, skip incoming data until possible start of
	 *       new packet
	 */
	int skip;
	__u8 data;

	spin_lock_irqsave(&garmin_data_p->lock, flags);
	dest = garmin_data_p->inbuffer;
	size = garmin_data_p->insize;
	dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
	skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
	spin_unlock_irqrestore(&garmin_data_p->lock, flags);

	/* dbg("%s - dle=%d skip=%d size=%d count=%d",
		__func__, dleSeen, skip, size, count); */

	if (size == 0)
		size = GSP_INITIAL_OFFSET;

	while (offs < count) {

		data = *(buf+offs);
		offs++;

		if (data == DLE) {
			if (skip) { /* start of a new pkt */
				skip = 0;
				size = GSP_INITIAL_OFFSET;
				dleSeen = 1;
			} else if (dleSeen) {
				dest[size++] = data;
				dleSeen = 0;
			} else {
				dleSeen = 1;
			}
		} else if (data == ETX) {
			if (dleSeen) {
				/* packet complete */

				data = dest[GSP_INITIAL_OFFSET];

				if (data == ACK) {
					ack_or_nak_seen = ACK;
					dbg("ACK packet complete.");
				} else if (data == NAK) {
					ack_or_nak_seen = NAK;
					dbg("NAK packet complete.");
				} else {
					dbg("packet complete - id=0x%X.",
						0xFF & data);
					gsp_rec_packet(garmin_data_p, size);
				}

				skip = 1;
				size = GSP_INITIAL_OFFSET;
				dleSeen = 0;
			} else {
				dest[size++] = data;
			}
		} else if (!skip) {

			if (dleSeen) {
				size = GSP_INITIAL_OFFSET;
				dleSeen = 0;
			}

			dest[size++] = data;
		}

		if (size >= GPS_IN_BUFSIZ) {
			dbg("%s - packet too large.", __func__);
			skip = 1;
			size = GSP_INITIAL_OFFSET;
			dleSeen = 0;
		}
	}

	spin_lock_irqsave(&garmin_data_p->lock, flags);

	garmin_data_p->insize = size;

	/* copy flags back to structure */
	if (skip)
		garmin_data_p->flags |= FLAGS_GSP_SKIP;
	else
		garmin_data_p->flags &= ~FLAGS_GSP_SKIP;

	if (dleSeen)
		garmin_data_p->flags |= FLAGS_GSP_DLESEEN;
	else
		garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN;

	spin_unlock_irqrestore(&garmin_data_p->lock, flags);

	if (ack_or_nak_seen) {
		if (gsp_next_packet(garmin_data_p) > 0)
			garmin_data_p->state = STATE_ACTIVE;
		else
			garmin_data_p->state = STATE_GSP_WAIT_DATA;
	}
	return count;
}