#include #include #include #include #include #include #include #define PACKET_RECV_ERROR_THRESHOLD 30 static uint16_t checksum(tabby_printer_packet *header, void *body) { uint16_t checksum = header->data[2] + header->data[3] + header->data[4] + header->data[5]; size_t i; for (i=0; isize; i++) { checksum += ((uint8_t *)body)[i]; } return checksum; } int tabby_printer_packet_recv(int fd, tabby_printer_packet *header, void *body) { ssize_t len; size_t i = 0, b = 0; uint8_t value; uint16_t sum = 0; memset(header, '\0', sizeof(*header)); while ((len = read(fd, &value, 1)) >= 0) { if (i == 0) { if (value == TABBY_PRINTER_SYNC_1) { header->preamble[0] = value; i++; } else { continue; } } else if (i == 1) { if (value == TABBY_PRINTER_SYNC_2) { header->preamble[1] = value; i++; } else { i = 0; continue; } } else if (i == 2) { header->type = value; i++; } else if (i == 3) { header->compression = value; i++; } else if (i == 4) { header->size = value; i++; } else if (i == 5) { header->size |= value << 8; i++; b = 0; } else if (b < header->size) { ((uint8_t *)body)[b++] = value; } else if (b == header->size) { sum = value; b++; } else if (b == header->size + 1) { sum |= value << 8; if (checksum(header, body) != sum) { errno = EIO; goto error_io; } return errno = 0; } } error_io: return -errno; } static inline int resend(tabby_printer_response *response) { if (response->device != TABBY_PRINTER_DEVICE_ID) { return 1; } if (response->status & (TABBY_PRINTER_ER0 | TABBY_PRINTER_SUM)) { return 1; } return 0; } int tabby_printer_packet_send(int fd, tabby_printer_packet *header, void *body, tabby_printer_response *response) { uint16_t sum = checksum(header, body); if (write(fd, header, sizeof(*header)) < 0) { goto error_io; } if (header->size) { if (write(fd, body, header->size) < 0) { goto error_io; } } if (write(fd, &sum, sizeof(sum)) < 0) { goto error_io; } if (read(fd, response, sizeof(*response)) < 0) { goto error_io; } return 0; error_io: return -1; } static void init_header(tabby_printer_packet *header, tabby_printer_packet_type type, size_t size) { header->preamble[0] = TABBY_PRINTER_SYNC_1; header->preamble[1] = TABBY_PRINTER_SYNC_2; header->type = type; header->compression = TABBY_PRINTER_COMPRESSION_NONE; header->size = (uint16_t)size; } int tabby_printer_init(int fd, tabby_printer_response *response) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INIT, 0); return tabby_printer_packet_send(fd, &header, NULL, response); } int tabby_printer_send_inquiry(int fd, tabby_printer_response *response) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INQUIRY, 0); return tabby_printer_packet_send(fd, &header, NULL, response); } int tabby_printer_job_start(int fd, uint8_t sheets, uint8_t linefeeds, uint8_t palette, uint8_t density, tabby_printer_response *response) { tabby_printer_packet header; uint8_t body[4] = { sheets, linefeeds, palette, density }; init_header(&header, TABBY_PRINTER_PACKET_JOB, sizeof(body)); return tabby_printer_packet_send(fd, &header, &body, response); } int tabby_printer_job_cancel(int fd, tabby_printer_response *response) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_CANCEL, 0); return tabby_printer_packet_send(fd, &header, NULL, response); } int tabby_printer_send_sheet(int fd, void *data, tabby_printer_response *response) { int i; size_t offset = 0; tabby_printer_packet header; for (i=0; i