/* * 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; }
/* * 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; }