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