Exemple #1
0
// beware: data field may be re-allocated in size !
int dusb_recv_data(CalcHandle* h, VirtualPacket* vtl)
{
	RawPacket raw = { 0 };
	uint8_t buf[64];
	int i = 0;
	long offset = 0;

	do
	{
		TRYF(dusb_recv(h, &raw));
		if(raw.type != RPKT_VIRT_DATA && raw.type != RPKT_VIRT_DATA_LAST)
			return ERR_INVALID_PACKET;

		if(!i++)
		{
			// first packet has a data header
			vtl->size = (raw.data[0] << 24) | (raw.data[1] << 16) | (raw.data[2] << 8) | (raw.data[3] << 0);
			vtl->type = (uint16_t)((raw.data[4] << 8) | (raw.data[5] << 0));
			vtl->data = realloc(vtl->data, vtl->size);
			memcpy(vtl->data, &raw.data[DH_SIZE], raw.size - DH_SIZE);
			offset = raw.size - DH_SIZE;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s\n\t\t(size = %08x, type = %s)", 
				raw.type == RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation",
				vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
			ticalcs_info("  TI->PC: %s", dusb_vpkt_type2name(vtl->type));
#endif
			if(vtl->type == 0xEE00)
				ticalcs_info("    Error Code : %04x\n", (vtl->data[0] << 8) | vtl->data[1]);
		}
		else
		{
			// others have more data
			memcpy(vtl->data + offset, raw.data, raw.size);
			offset += raw.size;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s", raw.type == RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation");
#endif

			h->updat->max1 = vtl->size;
			h->updat->cnt1 += DATA_SIZE;
			h->updat->pbar();
		}

		workaround_recv(h, &raw, vtl);

		TRYF(dusb_send_acknowledge(h));

	} while(raw.type != RPKT_VIRT_DATA_LAST);

	//printf("dusb_recv_data: rpkt.size=%d\n", raw.size);

	return 0;
}
Exemple #2
0
// beware: data field may be re-allocated in size !
TIEXPORT3 int TICALL dusb_recv_data_varsize(CalcHandle* handle, DUSBVirtualPacket* vtl, uint32_t* declared_size, uint32_t est_size)
{
	DUSBRawPacket raw;
	int i = 0;
	unsigned long alloc_size;
	int ret;

	VALIDATE_HANDLE(handle);
	VALIDATE_NONNULL(vtl);
	VALIDATE_NONNULL(declared_size);

	memset(&raw, 0, sizeof(raw));

	do
	{
		ret = dusb_recv(handle, &raw);
		if (ret)
		{
			break;
		}

		if (raw.type != DUSB_RPKT_VIRT_DATA && raw.type != DUSB_RPKT_VIRT_DATA_LAST)
		{
			ticalcs_critical("Unexpected raw packet type");
			ret = ERR_INVALID_PACKET;
			break;
		}

		if (!i++)
		{
			// first packet has a data header
			if (raw.size < DUSB_DH_SIZE)
			{
				ticalcs_critical("First raw packet is too small");
				ret = ERR_INVALID_PACKET;
				break;
			}

			if (raw.size > sizeof(raw.data))
			{
				ticalcs_critical("Raw packet is too large: %u bytes", raw.size);
				ret = ERR_INVALID_PACKET;
				break;
			}

			*declared_size = (((uint32_t)raw.data[0]) << 24) | (((uint32_t)raw.data[1]) << 16) | (((uint32_t)raw.data[2]) << 8) | (((uint32_t)raw.data[3]) << 0);
			alloc_size = (*declared_size > 10000 ? 10000 : *declared_size);

			if (alloc_size < raw.size - DUSB_DH_SIZE)
			{
				alloc_size = raw.size - DUSB_DH_SIZE;
			}

			vtl->type = (((uint16_t)raw.data[4]) << 8) | (raw.data[5] << 0);
			vtl->data = g_realloc(vtl->data, alloc_size);
			if (vtl->data != NULL)
			{
				memcpy(vtl->data, &raw.data[DUSB_DH_SIZE], raw.size - DUSB_DH_SIZE);
			}
			vtl->size = raw.size - DUSB_DH_SIZE;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s\n\t\t(size = %08x, type = %s)", 
				raw.type == DUSB_RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation",
				*declared_size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
			ticalcs_info("  TI->PC: %s", dusb_vpkt_type2name(vtl->type));
#endif
			if (vtl->data != NULL && vtl->type == 0xEE00)
			{
				ticalcs_info("    Error Code : %04x\n", (((int)vtl->data[0]) << 8) | vtl->data[1]);
			}
		}
		else
		{
			// others have more data

			if (vtl->size + raw.size > alloc_size)
			{
				if (vtl->size + raw.size <= est_size)
				{
					alloc_size = est_size;
				}
				else
				{
					alloc_size = (vtl->size + raw.size) * 2;
				}
				vtl->data = g_realloc(vtl->data, alloc_size);
			}

			memcpy(vtl->data + vtl->size, raw.data, raw.size);
			vtl->size += raw.size;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s", raw.type == DUSB_RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation");
#endif

			if (raw.type == DUSB_RPKT_VIRT_DATA_LAST)
			{
				handle->updat->max1 = vtl->size;
			}
			else if (vtl->size < *declared_size)
			{
				handle->updat->max1 = *declared_size;
			}
			else if (vtl->size < est_size)
			{
				handle->updat->max1 = est_size;
			}
			else
			{
				handle->updat->max1 = vtl->size + raw.size;
			}

			handle->updat->cnt1 = vtl->size;
			handle->updat->pbar();
		}

		workaround_recv(handle, &raw, vtl);

		ret = dusb_send_acknowledge(handle);
		if (ret)
		{
			break;
		}

	} while (raw.type != DUSB_RPKT_VIRT_DATA_LAST);

	//printf("dusb_recv_data: rpkt.size=%d\n", raw.size);

	return ret;
}
Exemple #3
0
TIEXPORT3 int TICALL dusb_send_data(CalcHandle *handle, DUSBVirtualPacket *vtl)
{
	DUSBRawPacket raw;
	int i, r, q;
	long offset;
	int ret;

	VALIDATE_HANDLE(handle);
	VALIDATE_NONNULL(vtl);
	if (vtl->size && !vtl->data)
	{
		return ERR_INVALID_PARAMETER;
	}

	memset(&raw, 0, sizeof(raw));

	do
	{
		if (vtl->size <= handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE)
		{
			// we have a single packet which is the last one, too
			raw.size = vtl->size + DUSB_DH_SIZE;
			raw.type = DUSB_RPKT_VIRT_DATA_LAST;

			raw.data[0] = MSB(MSW(vtl->size));
			raw.data[1] = LSB(MSW(vtl->size));
			raw.data[2] = MSB(LSW(vtl->size));
			raw.data[3] = LSB(LSW(vtl->size));
			raw.data[4] = MSB(vtl->type);
			raw.data[5] = LSB(vtl->type);
			if (vtl->data)
			{
				memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, vtl->size);
			}

			ret = dusb_send(handle, &raw);
			if (ret)
			{
				break;
			}
#if (VPKT_DBG == 2)
			ticalcs_info("  PC->TI: Virtual Packet Data Final\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
			ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
			workaround_send(handle, &raw, vtl);
			ret = dusb_recv_acknowledge(handle);
			if (ret)
			{
				break;
			}
		}
		else
		{
			// we have more than one packet: first packet has data header
			raw.size = handle->priv.dusb_rpkt_maxlen;
			raw.type = DUSB_RPKT_VIRT_DATA;

			raw.data[0] = MSB(MSW(vtl->size));
			raw.data[1] = LSB(MSW(vtl->size));
			raw.data[2] = MSB(LSW(vtl->size));
			raw.data[3] = LSB(LSW(vtl->size));
			raw.data[4] = MSB(vtl->type);
			raw.data[5] = LSB(vtl->type);
			memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE);
			offset = handle->priv.dusb_rpkt_maxlen - DUSB_DH_SIZE;

			ret = dusb_send(handle, &raw);
			if (ret)
			{
				break;
			}
#if (VPKT_DBG == 2)
			ticalcs_info("  PC->TI: Virtual Packet Data with Continuation\n\t\t(size = %08x, type = %s)", vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
			ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
			ret = dusb_recv_acknowledge(handle);
			if (ret)
			{
				break;
			}

			// other packets doesn't have data header but last one has a different type
			q = (vtl->size - offset) / handle->priv.dusb_rpkt_maxlen;
			r = (vtl->size - offset) % handle->priv.dusb_rpkt_maxlen;

			// send full chunks (no header)
			for (i = 1; i <= q; i++)
			{
				raw.size = handle->priv.dusb_rpkt_maxlen;
				raw.type = DUSB_RPKT_VIRT_DATA;
				memcpy(raw.data, vtl->data + offset, handle->priv.dusb_rpkt_maxlen);
				offset += handle->priv.dusb_rpkt_maxlen;

				ret = dusb_send(handle, &raw);
				if (ret)
				{
					goto end;
				}
#if (VPKT_DBG == 2)
				ticalcs_info("  PC->TI: Virtual Packet Data with Continuation");
#endif
				ret = dusb_recv_acknowledge(handle);
				if (ret)
				{
					goto end;
				}

				handle->updat->max1 = vtl->size;
				handle->updat->cnt1 += handle->priv.dusb_rpkt_maxlen;
				handle->updat->pbar();
			}

			// send last chunk (type)
			raw.size = r;
			raw.type = DUSB_RPKT_VIRT_DATA_LAST;
			memcpy(raw.data, vtl->data + offset, r);
			offset += r;

			ret = dusb_send(handle, &raw);
			if (ret)
			{
				break;
			}

#if (VPKT_DBG == 2)
			ticalcs_info("  PC->TI: Virtual Packet Data Final");
#endif
			// XXX is that workaround necessary on 83PCE/84+CE/84+CE-T ?
			if (handle->model != CALC_TI84P_USB && handle->model != CALC_TI84PC_USB && handle->model != CALC_TI82A_USB && handle->model != CALC_TI84PT_USB)
			{
				workaround_send(handle, &raw, vtl);
			}
			ret = dusb_recv_acknowledge(handle);
			if (ret)
			{
				break;
			}
		}
	} while(0);
end:

	return ret;
}
Exemple #4
0
// beware: data field may be re-allocated in size !
TIEXPORT3 int TICALL dusb_recv_data(CalcHandle* h, DUSBVirtualPacket* vtl)
{
	DUSBRawPacket raw;
	int i = 0;
	long offset = 0;

	if (h == NULL)
	{
		ticalcs_critical("%s: h is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}
	if (vtl == NULL)
	{
		ticalcs_critical("%s: vtl is NULL", __FUNCTION__);
		return ERR_INVALID_PACKET;
	}

	memset(&raw, 0, sizeof(raw));

	do
	{
		TRYF(dusb_recv(h, &raw));
		if(raw.type != DUSB_RPKT_VIRT_DATA && raw.type != DUSB_RPKT_VIRT_DATA_LAST)
			return ERR_INVALID_PACKET;

		if(!i++)
		{
			// first packet has a data header
			vtl->size = (raw.data[0] << 24) | (raw.data[1] << 16) | (raw.data[2] << 8) | (raw.data[3] << 0);
			vtl->type = (uint16_t)((raw.data[4] << 8) | (raw.data[5] << 0));
			vtl->data = g_realloc(vtl->data, vtl->size);
			memcpy(vtl->data, &raw.data[DUSB_DH_SIZE], raw.size - DUSB_DH_SIZE);
			offset = raw.size - DUSB_DH_SIZE;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s\n\t\t(size = %08x, type = %s)", 
				raw.type == DUSB_RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation",
				vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
			ticalcs_info("  TI->PC: %s", dusb_vpkt_type2name(vtl->type));
#endif
			if(vtl->type == 0xEE00)
				ticalcs_info("    Error Code : %04x\n", (vtl->data[0] << 8) | vtl->data[1]);
		}
		else
		{
			// others have more data
			memcpy(vtl->data + offset, raw.data, raw.size);
			offset += raw.size;
#if (VPKT_DBG == 2)
			ticalcs_info("  TI->PC: %s", raw.type == DUSB_RPKT_VIRT_DATA_LAST ? "Virtual Packet Data Final" : "Virtual Packet Data with Continuation");
#endif

			h->updat->max1 = vtl->size;
			h->updat->cnt1 += DATA_SIZE;
			h->updat->pbar();
		}

		workaround_recv(h, &raw, vtl);

		TRYF(dusb_send_acknowledge(h));

	} while(raw.type != DUSB_RPKT_VIRT_DATA_LAST);

	//printf("dusb_recv_data: rpkt.size=%d\n", raw.size);

	return 0;
}
Exemple #5
0
TIEXPORT3 int TICALL dusb_send_data(CalcHandle *h, DUSBVirtualPacket *vtl)
{
	DUSBRawPacket raw;
	int i, r, q;
	long offset;

	if (h == NULL)
	{
		ticalcs_critical("%s: h is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}
	if (vtl == NULL)
	{
		ticalcs_critical("%s: vtl is NULL", __FUNCTION__);
		return ERR_INVALID_PACKET;
	}

	memset(&raw, 0, sizeof(raw));

	if(vtl->size <= DATA_SIZE - DUSB_DH_SIZE)
	{
		// we have a single packet which is the last one, too
		raw.size = vtl->size + DUSB_DH_SIZE;
		raw.type = DUSB_RPKT_VIRT_DATA_LAST;

		raw.data[0] = MSB(MSW(vtl->size));
		raw.data[1] = LSB(MSW(vtl->size));
		raw.data[2] = MSB(LSW(vtl->size));
		raw.data[3] = LSB(LSW(vtl->size));
		raw.data[4] = MSB(vtl->type);
		raw.data[5] = LSB(vtl->type);
		memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, vtl->size);

		TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
		ticalcs_info("  PC->TI: Virtual Packet Data Final\n\t\t(size = %08x, type = %s)", 
			vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
		ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
		workaround_send(h, &raw, vtl);
		TRYF(dusb_recv_acknowledge(h));
	}
	else
	{
		// we have more than one packet: first packet has data header
		raw.size = DATA_SIZE;
		raw.type = DUSB_RPKT_VIRT_DATA;

		raw.data[0] = MSB(MSW(vtl->size));
		raw.data[1] = LSB(MSW(vtl->size));
		raw.data[2] = MSB(LSW(vtl->size));
		raw.data[3] = LSB(LSW(vtl->size));
		raw.data[4] = MSB(vtl->type);
		raw.data[5] = LSB(vtl->type);
		memcpy(&raw.data[DUSB_DH_SIZE], vtl->data, DATA_SIZE - DUSB_DH_SIZE);
		offset = DATA_SIZE - DUSB_DH_SIZE;

		TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
		ticalcs_info("  PC->TI: Virtual Packet Data with Continuation\n\t\t(size = %08x, type = %s)", 
			vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
		ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
		//workaround_send(h, &raw, vtl);
		TRYF(dusb_recv_acknowledge(h));

		// other packets doesn't have data header but last one has a different type
		q = (vtl->size - offset) / DATA_SIZE;
		r = (vtl->size - offset) % DATA_SIZE;

		// send full chunks (no header)
		for(i = 1; i <= q; i++)
		{
			raw.size = DATA_SIZE;
			raw.type = DUSB_RPKT_VIRT_DATA;
			memcpy(raw.data, vtl->data + offset, DATA_SIZE);
			offset += DATA_SIZE;

			TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
			ticalcs_info("  PC->TI: Virtual Packet Data with Continuation");
#endif
			TRYF(dusb_recv_acknowledge(h));

			h->updat->max1 = vtl->size;
			h->updat->cnt1 += DATA_SIZE;
			h->updat->pbar();
		}

		// send last chunk (type)
		//if(r)
		{
			raw.size = r;
			raw.type = DUSB_RPKT_VIRT_DATA_LAST;
			memcpy(raw.data, vtl->data + offset, r);
			offset += r;

			TRYF(dusb_send(h, &raw));

#if (VPKT_DBG == 2)
			ticalcs_info("  PC->TI: Virtual Packet Data Final");
#endif
			if (h->model != CALC_TI84P_USB)
			{
				workaround_send(h, &raw, vtl);
			}
			TRYF(dusb_recv_acknowledge(h));
		}
	}

	return 0;
}
int dusb_send_data(CalcHandle *h, VirtualPacket *vtl)
{
    RawPacket raw = { 0 };
    int i, r, q;
    long offset;

    if(vtl->size <= DATA_SIZE - DH_SIZE)
    {
        // we have a single packet which is the last one, too
        raw.size = vtl->size + DH_SIZE;
        raw.type = RPKT_VIRT_DATA_LAST;

        raw.data[0] = MSB(MSW(vtl->size));
        raw.data[1] = LSB(MSW(vtl->size));
        raw.data[2] = MSB(LSW(vtl->size));
        raw.data[3] = LSB(LSW(vtl->size));
        raw.data[4] = MSB(vtl->type);
        raw.data[5] = LSB(vtl->type);
        memcpy(&raw.data[DH_SIZE], vtl->data, vtl->size);

        TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
        ticalcs_info("  PC->TI: Virtual Packet Data Final\n\t\t(size = %08x, type = %s)",
                     vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
        ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
        TRYF(dusb_recv_acknowledge(h));
    }
    else
    {
        // we have more than one packet: first packet has data header
        raw.size = DATA_SIZE;
        raw.type = RPKT_VIRT_DATA;

        raw.data[0] = MSB(MSW(vtl->size));
        raw.data[1] = LSB(MSW(vtl->size));
        raw.data[2] = MSB(LSW(vtl->size));
        raw.data[3] = LSB(LSW(vtl->size));
        raw.data[4] = MSB(vtl->type);
        raw.data[5] = LSB(vtl->type);
        memcpy(&raw.data[DH_SIZE], vtl->data, DATA_SIZE - DH_SIZE);
        offset = DATA_SIZE - DH_SIZE;

        TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
        ticalcs_info("  PC->TI: Virtual Packet Data with Continuation\n\t\t(size = %08x, type = %s)",
                     vtl->size, dusb_vpkt_type2name(vtl->type));
#elif (VPKT_DBG == 1)
        ticalcs_info("  PC->TI: %s", dusb_vpkt_type2name(vtl->type));
#endif
        TRYF(dusb_recv_acknowledge(h));

        // other packets doesn't have data header but last one has a different type
        q = (vtl->size - offset) / DATA_SIZE;
        r = (vtl->size - offset) % DATA_SIZE;

        // send full chunks (no header)
        for(i = 1; i <= q; i++)
        {
            raw.size = DATA_SIZE;
            raw.type = RPKT_VIRT_DATA;
            memcpy(raw.data, vtl->data + offset, DATA_SIZE);
            offset += DATA_SIZE;

            TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
            ticalcs_info("  PC->TI: Virtual Packet Data with Continuation");
#endif
            TRYF(dusb_recv_acknowledge(h));

            h->updat->max1 = vtl->size;
            h->updat->cnt1 += DATA_SIZE;
            h->updat->pbar();
        }

        // send last chunk (type)
        if(r)
        {
            raw.size = r;
            raw.type = RPKT_VIRT_DATA_LAST;
            memcpy(raw.data, vtl->data + offset, r);
            offset += r;

            TRYF(dusb_send(h, &raw));
#if (VPKT_DBG == 2)
            ticalcs_info("  PC->TI: Virtual Packet Data Final");
#endif
            TRYF(dusb_recv_acknowledge(h));
        }
    }

    return 0;
}
Exemple #7
0
TIEXPORT3 int TICALL dusb_dissect(CalcModel model, FILE * f, const uint8_t * data, uint32_t len, uint8_t ep, uint8_t * first)
{
	int ret = 0;
	uint32_t raw_size;
	uint8_t raw_type;

	VALIDATE_NONNULL(f);
	VALIDATE_NONNULL(data);
	VALIDATE_NONNULL(first);

	if (len < 5 || len > sizeof(((DUSBRawPacket *)0)->data))
	{
		ticalcs_critical("Length %lu (%lX) is too small or too large for a valid DUSB raw packet", (unsigned long)len, (unsigned long)len);
		return ERR_INVALID_PACKET;
	}

	raw_size = (((uint32_t)(data[0])) << 24) | (((uint32_t)(data[1])) << 16) | (((uint32_t)(data[2])) << 8) | ((uint32_t)(data[3]));
	raw_type = data[4];

	fprintf(f, "%08lX (%02X)\t\t\t\t\t\t\t| %s: %s\n", (unsigned long)raw_size, (unsigned int)raw_type, ep_way(ep), dusb_rpkt_type2name(raw_type));

	if (raw_size > sizeof(((DUSBRawPacket *)0)->data) - 5)
	{
		ticalcs_critical("Raw size %lu (%lX) is too large for a valid DUSB raw packet", (unsigned long)raw_size, (unsigned long)raw_size);
		return ERR_INVALID_PACKET;
	}

	if (raw_type < 1 || raw_type > 5)
	{
		ticalcs_critical("Raw type unknown in DUSB raw packet");
		return ERR_INVALID_PACKET;
	}

	if (len < 5U + dusbrawpackets[raw_type - 1].data)
	{
		ticalcs_critical("Length %ld is too small for a valid data part in DUSB raw packet of type %u", (unsigned long)len, raw_type);
		return ERR_INVALID_PACKET;
	}

	switch (raw_type)
	{
		case DUSB_RPKT_BUF_SIZE_REQ:
		case DUSB_RPKT_BUF_SIZE_ALLOC:
		{
			uint32_t tmp = (((uint32_t)(data[5])) << 24) | (((uint32_t)(data[6])) << 16) | (((uint32_t)(data[7])) << 8) | ((uint32_t)(data[8]));
			fprintf(f, "\t[%08lX]\n", (unsigned long)tmp);
			if (len != 5U + 4)
			{
				fputs("(unexpected size for a packet of that type)\n", f);
			}
		}
		break;

		case DUSB_RPKT_VIRT_DATA:
		case DUSB_RPKT_VIRT_DATA_LAST:
		{
			if (*first)
			{
				uint32_t vtl_size = (((uint32_t)(data[5])) << 24) | (((uint32_t)(data[6])) << 16) | (((uint32_t)(data[7])) << 8) | ((uint32_t)(data[8]));
				uint16_t vtl_type = (((uint16_t)(data[9])) << 8) | ((uint16_t)(data[10]));
				fprintf(f, "\t%08lX {%04X}\t\t\t\t\t\t| CMD: %s\n", (unsigned long)vtl_size, vtl_type, dusb_vpkt_type2name(vtl_type));

				if (vtl_size != raw_size - 6)
				{
					fputs("(unexpected size for a packet of that type)\n", f);
				}

				if (!vtl_size)
				{
					fputs("(no data to dissect)\n", f);
				}
				else
				{
					uint32_t i;
					data += 11;
					len -= 11;
					if (len < vtl_size)
					{
						fputs("(packet truncated: insufficient given length)\n", f);
					}
					else if (len > vtl_size)
					{
						fputs("(given length larger than length in packet)\n", f);
					}
					fprintf(f, "\t\t");
					for (i = 0; i < len;)
					{
						fprintf(f, "%02X ", *data++);
						if (!(++i & 15))
						{
							fprintf(f, "\n\t\t");
						}
					}
					data -= vtl_size;
					fputc('\n', f);
					ret = dusb_dissect_cmd_data(model, f, data, len, vtl_size, vtl_type);
					if (ret)
					{
						fputs("(inner data dissection had a problem with the packet)\n", f);
					}
				}
			}
			else
			{
				uint32_t i;
				fprintf(f, "\t%02X %02X %02X ", data[5], data[6], data[7]);
				data += 8;
				len -= 8;
				if (len < raw_size - 3)
				{
					fputs("(packet truncated: insufficient given length)\n", f);
					raw_size = len;
				}
				else if (len > raw_size - 3)
				{
					fputs("(given length larger than length in packet)\n", f);
				}
				for (i = 0; i < len;)
				{
					fprintf(f, "%02X ", *data++);
					if (!(++i & 15))
					{
						fprintf(f, "\n\t\t");
					}
				}
				fputc('\n', f);
			}
			*first = (raw_type == DUSB_RPKT_VIRT_DATA) ? 0 : 1;
		}
		break;


		case DUSB_RPKT_VIRT_DATA_ACK:
		{
			uint16_t tmp = (((uint16_t)(data[5])) << 8) | ((uint16_t)(data[6]));
			fprintf(f, "\t[%04X]\n", tmp);
			if (len != 5 + 2)
			{
				fputs("(unexpected size for a packet of that type)\n", f);
			}
		}
		break;
	}

	return ret;
}