TIEXPORT3 int TICALL dusb_recv(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[5]; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(pkt); // Any packet has always an header of 5 bytes (size & type) ticables_progress_reset(handle->cable); ret = ticables_cable_recv(handle->cable, buf, 5); while (!ret) { pkt->size = buf[3] | (((uint32_t)buf[2]) << 8) | (((uint32_t)buf[1]) << 16) | (((uint32_t)buf[0]) << 24); pkt->type = buf[4]; if ( (handle->model == CALC_TI84P_USB || handle->model == CALC_TI84PC_USB || handle->model == CALC_TI82A_USB || handle->model == CALC_TI84PT_USB) && pkt->size > 250) { ticalcs_warning("Raw packet is unexpectedly large: %u bytes", pkt->size); } else if ( (handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) && pkt->size > 1018) { ticalcs_warning("Raw packet is unexpectedly large: %u bytes", pkt->size); } else if (handle->model == CALC_TI89T_USB) { // Fall through. } // else do nothing for now. if (pkt->size > sizeof(pkt->data)) { ticalcs_critical("Raw packet is too large: %u bytes", pkt->size); ret = ERR_INVALID_PACKET; break; } //printf("dusb_send: pkt->size=%d\n", pkt->size); // Next, follows data ret = ticables_cable_recv(handle->cable, pkt->data, pkt->size); if (!ret) { if (pkt->size >= 128) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); } if (handle->updat->cancel) { ret = ERR_ABORT; } } break; } return ret; }
// Work around TI's OS behaviour: extra bulk read of 0 size required after the last raw packet in a transfer, // when some conditions are met. static void workaround_recv(CalcHandle *handle, DUSBRawPacket * raw, DUSBVirtualPacket * vtl) { uint8_t buf[64]; ticalcs_info("workaround_recv: vtl->size=%d\traw->size=%d", vtl->size, raw->size); if (handle->model == CALC_TI89T_USB) { if ((raw->size % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(handle->cable, buf, 0); } } else if (handle->model == CALC_TI84P_USB || handle->model == CALC_TI84PC_USB || handle->model == CALC_TI82A_USB || handle->model == CALC_TI84PT_USB) { if (((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(handle->cable, buf, 0); } } else if (handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) { // These models don't seem to need receive workarounds. } else { ticalcs_warning("XXX unhandled model in workaround_recv"); } }
TIEXPORT3 int TICALL dusb_send_buf_size_alloc(CalcHandle* handle, uint32_t size) { DUSBRawPacket raw; int ret; VALIDATE_HANDLE(handle); if (size > sizeof(raw.data) + 1) { ticalcs_warning("Clamping dubious large DUSB buffer size request"); size = sizeof(raw.data) + 1; } memset(&raw, 0, sizeof(raw)); raw.size = 4; raw.type = DUSB_RPKT_BUF_SIZE_ALLOC; raw.data[0] = (size >> 24) & 0xFF; raw.data[1] = (size >> 16) & 0xFF; raw.data[2] = (size >> 8) & 0xFF; raw.data[3] = (size ) & 0xFF; ret = dusb_send(handle, &raw); if (!ret) { ticalcs_info(" PC->TI: Buffer Size Allocation (%i bytes)", size); } handle->priv.dusb_rpkt_maxlen = size; return ret; }
static int err_code(uint8_t code) { int i; for(i = 0; i < (int)(sizeof(usb_errors) / sizeof(usb_errors[0])); i++) if(usb_errors[i] == code) return i+1; ticalcs_warning("Nspire error code 0x%02x not found in list. Please report it at <*****@*****.**>.", (int)code); return 0; }
static int err_code(uint8_t *data) { int i; int code = data[2]; ticalcs_info(" TI->PC: SKP (%02x)", data[0]); for(i = 0; i < (int)(sizeof(dbus_errors) / sizeof(dbus_errors[0])); i++) if(dbus_errors[i] == code) return i+1; ticalcs_warning("D-BUS error code not found in list. Please report it at <*****@*****.**>."); return 0; }
static int err_code(uint16_t code) { unsigned int i; for (i = 0; i < sizeof(usb_errors) / sizeof(usb_errors[0]); i++) { if (usb_errors[i] == code) { return i + 1; } } ticalcs_warning("USB error code 0x%02x not found in list. Please report it at <*****@*****.**>.", code); return 0; }
TIEXPORT3 int TICALL dusb_recv_data(CalcHandle* handle, DUSBVirtualPacket* vtl) { uint32_t declared_size; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(vtl); ret = dusb_recv_data_varsize(handle, vtl, &declared_size, 0); if (!ret) { if (declared_size != vtl->size) { ticalcs_warning("invalid packet (declared size = %d, actual size = %d)", declared_size, vtl->size); ret = ERR_INVALID_PACKET; } } return ret; }
// Work around TI's OS behaviour: extra bulk write of 0 size required after the last raw packet in a transfer, // when some conditions are met. static void workaround_send(CalcHandle *handle, DUSBRawPacket *raw, DUSBVirtualPacket *vtl) { uint8_t buf[64]; ticalcs_info("workaround_send: vtl->size=%d\traw->size=%d", vtl->size, raw->size); if (handle->model == CALC_TI89T_USB) { // A 1076-byte (string) variable doesn't require this workaround, but bigger (string) variables do. if (vtl->size > 1076 && ((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk write\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_send(handle->cable, buf, 0); } } else if (handle->model == CALC_TI84P_USB || handle->model == CALC_TI84PC_USB || handle->model == CALC_TI82A_USB || handle->model == CALC_TI84PT_USB) { // A 244-byte (program) variable doesn't require this workaround, but bigger (program) variables do. if (raw->type == DUSB_RPKT_VIRT_DATA_LAST && vtl->size > 244 && (vtl->size % 250) == 244) { ticalcs_info("XXX triggering an extra bulk write\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_send(handle->cable, buf, 0); } } else if (handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) { if (raw->type == DUSB_RPKT_VIRT_DATA_LAST && ((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk write\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_send(handle->cable, buf, 0); } } else { ticalcs_warning("XXX unhandled model in workaround_send"); } }
// 0x0010: modify/rename/delete variable TIEXPORT3 int TICALL dusb_cmd_s_var_modify(CalcHandle *handle, const char *src_folder, const char *src_name, unsigned int n_src_attrs, const DUSBCalcAttr **src_attrs, const char *dst_folder, const char *dst_name, unsigned int n_dst_attrs, const DUSBCalcAttr **dst_attrs) { DUSBVirtualPacket* pkt; unsigned int i; unsigned int j = 0; unsigned int pks; int retval = 0; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(src_folder); VALIDATE_NONNULL(src_name); VALIDATE_NONNULL(src_attrs); VALIDATE_NONNULL(dst_folder); VALIDATE_NONNULL(dst_name); VALIDATE_ATTRS(n_dst_attrs, dst_attrs); pks = 2 + strlen(src_name)+1 + 2; if (strlen(src_folder)) { pks += strlen(src_folder)+1; } for (i = 0; i < n_src_attrs; i++) { pks += 4 + src_attrs[i]->size; } pks += 5; if (strlen(dst_folder)) { pks += strlen(dst_folder)+1; } if (strlen(dst_name)) { pks += strlen(dst_name)+1; } for (i = 0; i < n_dst_attrs; i++) { pks += 4 + dst_attrs[i]->size; } pkt = dusb_vtl_pkt_new_ex(handle, pks, DUSB_VPKT_MODIF_VAR, dusb_vtl_pkt_alloc_data(pks)); if (strlen(src_folder)) { pkt->data[j++] = strlen(src_folder); memcpy(pkt->data + j, src_folder, strlen(src_folder)+1); j += strlen(src_folder)+1; } else { pkt->data[j++] = 0; } pkt->data[j++] = strlen(src_name); memcpy(pkt->data + j, src_name, strlen(src_name)+1); j += strlen(src_name)+1; pkt->data[j++] = MSB(n_src_attrs); pkt->data[j++] = LSB(n_src_attrs); for (i = 0; i < n_src_attrs; i++) { pkt->data[j++] = MSB(src_attrs[i]->id); pkt->data[j++] = LSB(src_attrs[i]->id); pkt->data[j++] = MSB(src_attrs[i]->size); pkt->data[j++] = LSB(src_attrs[i]->size); memcpy(pkt->data + j, src_attrs[i]->data, src_attrs[i]->size); j += src_attrs[i]->size; } pkt->data[j++] = 0x01; /* ??? */ if (strlen(dst_folder)) { pkt->data[j++] = strlen(dst_folder); memcpy(pkt->data + j, dst_folder, strlen(dst_folder)+1); j += strlen(dst_folder)+1; } else { pkt->data[j++] = 0; } if (strlen(dst_name)) { pkt->data[j++] = strlen(dst_name); memcpy(pkt->data + j, dst_name, strlen(dst_name)+1); j += strlen(dst_name)+1; } else { pkt->data[j++] = 0; } pkt->data[j++] = MSB(n_dst_attrs); pkt->data[j++] = LSB(n_dst_attrs); for (i = 0; i < n_dst_attrs; i++) { pkt->data[j++] = MSB(dst_attrs[i]->id); pkt->data[j++] = LSB(dst_attrs[i]->id); pkt->data[j++] = MSB(dst_attrs[i]->size); pkt->data[j++] = LSB(dst_attrs[i]->size); memcpy(pkt->data + j, dst_attrs[i]->data, dst_attrs[i]->size); j += dst_attrs[i]->size; } if (j == pks) { retval = dusb_send_data(handle, pkt); } else { // Really shouldn't occur. ticalcs_warning("Discrepancy in packet generation, not sending it"); retval = ERR_INVALID_PACKET; } ticalcs_info(" src_folder=%s, name=%s, nattrs=%i", src_folder, src_name, n_src_attrs); ticalcs_info(" dst_folder=%s, name=%s, nattrs=%i", dst_folder, dst_name, n_dst_attrs); dusb_vtl_pkt_del(handle, pkt); return retval; }