public void write( byte[] data, int off, int len ) {
		assert data != null;
		assert off >= 0;
		assert data.length >= off+len;
		
		int wLen = len+3; // Total length of block+framing if written as a WHOLEBLOCK 
		
		// If it would fit in a single packet, but not in the current one, flush first.
		if( bufPos+wLen > buffer.length && wLen <= buffer.length ) flush();
		
		if( bufPos+wLen > buffer.length ) {
			crcCalculator.reset();
			crcCalculator.update(data, off, len);
			int crc = (int)crcCalculator.getValue();
			int hLen = 1+4+3+3+2;
			// TODO: Try harder to minimize number of packets
			if( bufPos+hLen >= buffer.length ) flush();
			
			int wrote = 0;
			while( wrote < len ) {
				int segLen = Math.min(len-wrote, buffer.length-bufPos-hLen);
				
				buffer[bufPos++] = UBTP.OP_SEGMENT;
				buffer[bufPos++] = (byte)(crc >> 24);
				buffer[bufPos++] = (byte)(crc >> 16);
				buffer[bufPos++] = (byte)(crc >>  8);
				buffer[bufPos++] = (byte)(crc >>  0);
				buffer[bufPos++] = (byte)(len >> 16);
				buffer[bufPos++] = (byte)(len >>  8);
				buffer[bufPos++] = (byte)(len >>  0);
				buffer[bufPos++] = (byte)(wrote >> 16);
				buffer[bufPos++] = (byte)(wrote >>  8);
				buffer[bufPos++] = (byte)(wrote >>  0);
				buffer[bufPos++] = (byte)(segLen >> 8);
				buffer[bufPos++] = (byte)(segLen >> 0);
				for( int i=0; i<segLen; ++i, ++wrote, ++bufPos ) {
					buffer[bufPos] = data[off+wrote];
				}
				flush();
			}
		} else {
			assert bufPos+len+3 <= buffer.length;
			buffer[bufPos++] = UBTP.OP_WHOLEBLOCK;
			buffer[bufPos++] = (byte)(len >> 8);
			buffer[bufPos++] = (byte)(len >> 0);
			for( int i=0; i<len; ++i ) {
				buffer[bufPos++] = data[off+i];
			}
		}
		
		if( bufPos + 4 >= buffer.length ) flush();
	}