Пример #1
0
/*
 * called for a complete packet received from tty layer
 *
 * the complete packet (pktid ... cksum) is in garmin_data_p->inbuf starting
 * at GSP_INITIAL_OFFSET.
 *
 * count - number of bytes in the input buffer including space reserved for
 *         the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
 *         (including pkt-id, data-length a. cksum)
 */
static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
{
	unsigned long flags;
	const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
	__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;

	int cksum = 0;
	int n = 0;
	int pktid = recpkt[0];
	int size = recpkt[1];

	usb_serial_debug_data(debug, &garmin_data_p->port->dev,
			       __func__, count-GSP_INITIAL_OFFSET, recpkt);

	if (size != (count-GSP_INITIAL_OFFSET-3)) {
		dbg("%s - invalid size, expected %d bytes, got %d",
			__func__, size, (count-GSP_INITIAL_OFFSET-3));
		return -EINVPKT;
	}

	cksum += *recpkt++;
	cksum += *recpkt++;

	/* sanity check, remove after test ... */
	if ((__u8 *)&(usbdata[3]) != recpkt) {
		dbg("%s - ptr mismatch %p - %p",
			__func__, &(usbdata[4]), recpkt);
		return -EINVPKT;
	}

	while (n < size) {
		cksum += *recpkt++;
		n++;
	}

	if ((0xff & (cksum + *recpkt)) != 0) {
		dbg("%s - invalid checksum, expected %02x, got %02x",
			__func__, 0xff & -cksum, 0xff & *recpkt);
		return -EINVPKT;
	}

	usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
	usbdata[1] = __cpu_to_le32(pktid);
	usbdata[2] = __cpu_to_le32(size);

	garmin_write_bulk(garmin_data_p->port, garmin_data_p->inbuffer,
			   GARMIN_PKTHDR_LENGTH+size, 0);

	/* if this was an abort-transfer command, flush all
	   queued data. */
	if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
		spin_lock_irqsave(&garmin_data_p->lock, flags);
		garmin_data_p->flags |= FLAGS_DROP_DATA;
		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
		pkt_clear(garmin_data_p);
	}

	return count;
}
static int garmin_init_session(struct usb_serial_port *port)
{
	struct usb_serial *serial = port->serial;
	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
	int status = 0;
	int i = 0;

	if (status == 0) {
		usb_kill_urb(port->interrupt_in_urb);

		dev_dbg(&serial->dev->dev, "%s - adding interrupt input\n", __func__);
		status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
		if (status)
			dev_err(&serial->dev->dev,
			  "%s - failed submitting interrupt urb, error %d\n",
							__func__, status);
	}

	/*
	 * using the initialization method from gpsbabel. See comments in
	 * gpsbabel/jeeps/gpslibusb.c gusb_reset_toggles()
	 */
	if (status == 0) {
		dev_dbg(&serial->dev->dev, "%s - starting session ...\n", __func__);
		garmin_data_p->state = STATE_ACTIVE;

		for (i = 0; i < 3; i++) {
			status = garmin_write_bulk(port,
					GARMIN_START_SESSION_REQ,
					sizeof(GARMIN_START_SESSION_REQ), 0);

			if (status < 0)
				break;
		}

		if (status > 0)
			status = 0;
	}

	return status;
}
/*
 * Called for data received from tty
 *
 * The input data is expected to be in garmin usb-packet format.
 *
 * buf contains the data read, it may span more than one packet
 * or even incomplete packets
 */
static int nat_receive(struct garmin_data *garmin_data_p,
		       const unsigned char *buf, int count)
{
	unsigned long flags;
	__u8 *dest;
	int offs = 0;
	int result = count;
	int len;

	while (offs < count) {
		/* if buffer contains header, copy rest of data */
		if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH)
			len = GARMIN_PKTHDR_LENGTH
			      +getDataLength(garmin_data_p->inbuffer);
		else
			len = GARMIN_PKTHDR_LENGTH;

		if (len >= GPS_IN_BUFSIZ) {
			/* seems to be an invalid packet, ignore rest
			   of input */
			dev_dbg(&garmin_data_p->port->dev,
				"%s - packet size too large: %d\n",
				__func__, len);
			garmin_data_p->insize = 0;
			count = 0;
			result = -EINVPKT;
		} else {
			len -= garmin_data_p->insize;
			if (len > (count-offs))
				len = (count-offs);
			if (len > 0) {
				dest = garmin_data_p->inbuffer
						+ garmin_data_p->insize;
				memcpy(dest, buf+offs, len);
				garmin_data_p->insize += len;
				offs += len;
			}
		}

		/* do we have a complete packet ? */
		if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH) {
			len = GARMIN_PKTHDR_LENGTH+
			   getDataLength(garmin_data_p->inbuffer);
			if (garmin_data_p->insize >= len) {
				garmin_write_bulk(garmin_data_p->port,
						   garmin_data_p->inbuffer,
						   len, 0);
				garmin_data_p->insize = 0;

				/* if this was an abort-transfer command,
				   flush all queued data. */
				if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
					spin_lock_irqsave(&garmin_data_p->lock,
									flags);
					garmin_data_p->flags |= FLAGS_DROP_DATA;
					spin_unlock_irqrestore(
						&garmin_data_p->lock, flags);
					pkt_clear(garmin_data_p);
				}
			}
		}
	}
	return result;
}