diff options
Diffstat (limited to 'src/escputil')
-rw-r--r-- | src/escputil/d4lib.c | 172 | ||||
-rw-r--r-- | src/escputil/d4lib.h | 6 | ||||
-rw-r--r-- | src/escputil/escputil.c | 173 |
3 files changed, 222 insertions, 129 deletions
diff --git a/src/escputil/d4lib.c b/src/escputil/d4lib.c index 17cd4ae..3c98f81 100644 --- a/src/escputil/d4lib.c +++ b/src/escputil/d4lib.c @@ -67,6 +67,8 @@ static signalHandler_t sig; static int timeoutGot = 0; static int _readData(int fd, unsigned char *buf, int len); +static int d4Errno = 0; + /* commands for the D4 protocol Transaction Cmd Reply @@ -305,7 +307,8 @@ static int printError(unsigned char errorNb) { if ( msg->result == errorNb ) { - fprintf(stderr,"%s\n", msg->message); + if (debugD4) + fprintf(stderr,"%s\n", msg->message); return msg->errorClass; } msg++; @@ -326,9 +329,11 @@ static int printError(unsigned char errorNb) static void printCmdType(unsigned char *cmd) { + if (cmd[6] & 0x80) + fprintf(stderr, ">>>"); if ( cmd[0] == 0 && cmd[1] == 0 ) { - switch(cmd[6]) + switch(cmd[6] & 0x7f) { case 0: fprintf(stderr,"--- Init ---\n");break; case 1: fprintf(stderr,"--- OpenChannel ---\n");break; @@ -436,7 +441,7 @@ static int writeCmd(int fd, unsigned char *cmd, int len) /* */ /*******************************************************************/ -int readAnswer(int fd, unsigned char *buf, int len) +int readAnswer(int fd, unsigned char *buf, int len, int allowExtra) { int rd = 0; int total = 0; @@ -445,6 +450,7 @@ int readAnswer(int fd, unsigned char *buf, int len) long dt; int count = 0; int first_read = 1; + int excess = 0; /* wait a little bit before reading an answer */ usleep(d4RdTimeout); @@ -508,15 +514,50 @@ int readAnswer(int fd, unsigned char *buf, int len) /* in case of errors this may differ from */ /* the expected lenght. Setting len to this */ /* value will avoid waiting for timeout */ - len = (buf[2] << 8) + buf[3]; - len = (len > sizeof(buf))?sizeof(buf) - 1:len; + int newlen = (buf[2] << 8) + buf[3]; + if (len > newlen) + { + if (debugD4) + fprintf(stderr, "Changing len from %d to %d\n", len, newlen); + len = newlen; + } + else if (len < newlen) + { + excess = newlen - len; + if (debugD4) + fprintf(stderr, "Expected %d, getting %d, %sflushing %d\n", + len, newlen, allowExtra ? "not " : "", excess); + } } } usleep(d4RdTimeout); } + if (! allowExtra) + { + int retry_count = 0; + while (excess > 0) + { + char wastebuf[256]; + int bytes = excess > 256 ? 256 : excess; + int status = read(fd, wastebuf, bytes); + if (status < 0) + break; + else if (status == 0 && retry_count > 2) + break; + else if (status == 0) + retry_count++; + else + retry_count = 0; + if (status < bytes) + usleep(d4RdTimeout); + printHexValues("waste", (const unsigned char *) wastebuf, status); + excess -= status; + } + } if ( debugD4 ) { + printCmdType(buf); # if PTIME gettimeofday(&end, NULL); # endif @@ -673,15 +714,16 @@ static int _readData(int fd, unsigned char *buf, int len) /* */ /*******************************************************************/ -static int sendReceiveCmd(int fd, unsigned char *cmd, int len, unsigned char *answer, int expectedlen) +static int sendReceiveCmd(int fd, unsigned char *cmd, int len, unsigned char *answer, int expectedlen, int allowExtra) { int rd; + d4Errno = 0; if ( (rd = writeCmd(fd, cmd, len ) ) != len ) { if ( rd < 0 ) return -1; return 0; } - rd = readAnswer(fd, answer, expectedlen ); + rd = readAnswer(fd, answer, expectedlen, allowExtra ); if ( rd == 0 ) { /* no answer from device */ @@ -700,10 +742,12 @@ static int sendReceiveCmd(int fd, unsigned char *cmd, int len, unsigned char *an if ( answer[6] == 0x7f ) { printError(answer[9]); + d4Errno = answer[9]; return -1; } else if ( answer[7] != 0 ) { + d4Errno = answer[7]; if ( printError(answer[7]) ) { return -1; @@ -742,7 +786,7 @@ Loop: { return 0; } - rd = readAnswer(fd, buf, 8); + rd = readAnswer(fd, buf, 8, 0); if ( rd == 0 ) { /* no answer from device */ @@ -789,7 +833,7 @@ int Init(int fd) cmd.head.command = 0; cmd.revision = 0x10; - rd = sendReceiveCmd(fd, (unsigned char*)&cmd, sizeof(cmd), buf, 9 ); + rd = sendReceiveCmd(fd, (unsigned char*)&cmd, sizeof(cmd), buf, 9, 0 ); return rd == 9 ? 1 : 0; } @@ -815,7 +859,7 @@ int Exit(int fd) cmd.control = 0; cmd.command = 8; - rd = sendReceiveCmd(fd, (unsigned char*)&cmd, sizeof(cmd), buf, 8 ); + rd = sendReceiveCmd(fd, (unsigned char*)&cmd, sizeof(cmd), buf, 8, 0 ); return rd > 0 ? 1 : rd; } @@ -846,7 +890,7 @@ int GetSocketID(int fd, const char *serviceName) cmd->command = 0x09; strcpy(buf + sizeof(cmdHeader_t), serviceName); - rd = sendReceiveCmd(fd, (unsigned char*)buf, len, rBuf, len + 2); + rd = sendReceiveCmd(fd, (unsigned char*)buf, len, rBuf, len + 2, 0); if ( rd > 0 ) { return rBuf[8]; @@ -873,8 +917,9 @@ int OpenChannel(int fd, unsigned char sockId, int *sndSz, int *rcvSz) unsigned char cmd[17]; unsigned char buf[20]; int rd; + int i; - for(;;) + for(i = 0; i < 5; i++) /* Retry count */ { cmd[0] = 0; /* transaction sockets */ cmd[1] = 0; @@ -894,10 +939,20 @@ int OpenChannel(int fd, unsigned char sockId, int *sndSz, int *rcvSz) cmd[15] = 0; /* initial credit for us ? */ cmd[16] = 0; - rd = sendReceiveCmd(fd, cmd, 17, buf, 16); + rd = sendReceiveCmd(fd, cmd, 17, buf, 16, 0); if ( rd == -1 ) { - return -1; + if (debugD4) + fprintf(stderr, "OpenChannel %d fails, error %d\n", sockId, d4Errno); + if (d4Errno == 6) /* channel already open */ + { + if ( debugD4 ) + fprintf(stderr, "Channel %d already open, closing\n", sockId); + CloseChannel(fd, sockId); + continue; + } + else + return -1; } else if ( rd == 16 ) { @@ -908,6 +963,8 @@ int OpenChannel(int fd, unsigned char sockId, int *sndSz, int *rcvSz) } else if ( buf[7] != 0 ) { + if (debugD4) + fprintf(stderr, "OpenChannel %d fails, hard error\n", sockId); /* hard error */ return -1; } @@ -917,7 +974,16 @@ int OpenChannel(int fd, unsigned char sockId, int *sndSz, int *rcvSz) } else { + if (d4Errno == 6) /* channel already open */ + { + if ( debugD4 ) + fprintf(stderr, "Channel %d already open, closing\n", sockId); + CloseChannel(fd, sockId); + continue; + } /* at this stage we can only have an error */ + if (debugD4) + fprintf(stderr, "OpenChannel %d fails, wrong count %d\n", sockId, rd); return -1; } } @@ -949,7 +1015,7 @@ int CloseChannel(int fd, unsigned char socketID) buf[sizeof(cmdHeader_t)+0] = socketID; buf[sizeof(cmdHeader_t)+1] = socketID; buf[sizeof(cmdHeader_t)+2] = 0; - rd = sendReceiveCmd(fd, buf,10, buf, 10); + rd = sendReceiveCmd(fd, buf,10, buf, 10, 0); return rd == 10 ? 1 : rd; } @@ -982,7 +1048,7 @@ int CreditRequest(int fd, unsigned char socketID) buf[sizeof(cmdHeader_t)+3] = 0x80; buf[sizeof(cmdHeader_t)+4] = 0xff; buf[sizeof(cmdHeader_t)+5] = 0xff; - rd = sendReceiveCmd(fd, buf, 13, rBuf, 12); + rd = sendReceiveCmd(fd, buf, 13, rBuf, 12, 0); if ( rd == 12 ) { /* this is the credit */ @@ -1023,7 +1089,7 @@ int Credit(int fd, unsigned char socketID, int credit) buf[sizeof(cmdHeader_t)+1] = socketID; buf[sizeof(cmdHeader_t)+2] = credit >> 8; buf[sizeof(cmdHeader_t)+3] = credit & 0xff; - rd = sendReceiveCmd(fd, buf, 11, rBuf, 10); + rd = sendReceiveCmd(fd, buf, 11, rBuf, 10, 0); if ( rd == 10 ) { return 1; @@ -1039,7 +1105,7 @@ int Credit(int fd, unsigned char socketID, int credit) /* Convenience function */ /* handle the CreditRequest command */ /* Input: int fd file handle */ -/* unsigned char socketID */ +/* unsigned char socketID */ /* IN/Out int *sndSize for error handling */ /* IN/Out int *rcvSize for error handling */ /* */ @@ -1054,10 +1120,11 @@ int askForCredit(int fd, unsigned char socketID, int *sndSize, int *rcvSize) { int credit = 0; int count = 0; + int retries = 10; - while (credit == 0 ) + while (credit == 0 && retries-- >= 0 ) { - while((credit=CreditRequest(fd,socketID)) == 0 && count < MAX_CREDIT_REQUEST ) + while((credit=CreditRequest(fd,socketID)) == 0 && count < MAX_CREDIT_REQUEST && retries-- >= 0) usleep(d4RdTimeout); if ( credit == -1 ) @@ -1069,8 +1136,11 @@ int askForCredit(int fd, unsigned char socketID, int *sndSize, int *rcvSize) credit = 0; /* init printer and reopen the printer channel */ CloseChannel(fd, socketID); + socketID = GetSocketID(fd, "EPSON-CTRL"); if ( Init(fd) ) { + if (debugD4) + fprintf(stderr, "askForCredit init succeeded, now try to open\n"); OpenChannel(fd, socketID, sndSize, rcvSize); } } @@ -1087,8 +1157,8 @@ int askForCredit(int fd, unsigned char socketID, int *sndSize, int *rcvSize) /* Convenience function */ /* write the data to the device */ /* Input: int fd file handle */ -/* unsigned char socketID the deetination socket */ -/* unsigned char *buf the datas to be send */ +/* unsigned char socketID the deetination socket */ +/* unsigned char *buf the datas to be send */ /* int len how many datas are to we send */ /* int eoj set out of band flag if eoj set */ /* */ @@ -1177,11 +1247,11 @@ int writeData(int fd, unsigned char socketID, const unsigned char *buf, int len, /* Convenience function */ /* give credit and read then the expected datas */ /* Input: int fd file handle */ -/* unsigned char socketID the destination socket */ -/* unsigned char *buf the datas to be send */ +/* unsigned char socketID the destination socket */ +/* unsigned char *buf the datas to be send */ /* int len howmany datas are to we send */ /* */ -/* Return: number of bytes written or -1; */ +/* Return: number of bytes read or -1; */ /* */ /*******************************************************************/ @@ -1203,6 +1273,58 @@ int readData(int fd, unsigned char socketID, unsigned char *buf, int len) } /*******************************************************************/ +/* Function writeAndReadData() */ +/* Convenience function */ +/* give credit and read then the expected datas */ +/* Input: int fd file handle */ +/* unsigned char socketID the destination socket */ +/* unsigned char *cmd the datas to be send */ +/* int cmd_len howmany datas are to we send */ +/* int eoj set out of band flag if eoj set */ +/* unsigned char *buf the datas to be send */ +/* int *sndSz Send buffer size */ +/* int *rcvSz Receive buffer size */ +/* int len how many datas are to we send */ +/* fptr test function to verify buffer contents */ +/* */ +/* Return: number of bytes read or -1; */ +/* */ +/* This allows us to give credit before sending the command. */ +/* Sending the command and then giving credit sometimes causes */ +/* the actual data to be sent as a reply to the credit command. */ +/* */ +/*******************************************************************/ + +int writeAndReadData(int fd, unsigned char socketID, + const unsigned char *cmd, int cmd_len, int eoj, + unsigned char *buf, int len, int *sndSz, int *rcvSz, + int (*test)(const unsigned char *buf)) +{ + int ret; + int retry = 5; + int credit = askForCredit(fd, socketID, sndSz, rcvSz); + if (credit < 0) + return -1; + /* give credit */ + if ( Credit(fd, socketID, 1) == 1 ) + { + if (writeData(fd, socketID, cmd, cmd_len, eoj) <= 0) + return -1; + /* wait a little bit */ + do + { + usleep(1000); + ret = _readData(fd, buf, len); + if (ret < 0) + return ret; + } while (retry-- >= 0 && (!test || !(*test)(buf))); + return ret; + } + else + return -1; +} + +/*******************************************************************/ /* Function readData() */ /* Convenience function */ /* give credit and read then the expected datas */ diff --git a/src/escputil/d4lib.h b/src/escputil/d4lib.h index 41a6c6b..76aebd3 100644 --- a/src/escputil/d4lib.h +++ b/src/escputil/d4lib.h @@ -35,7 +35,11 @@ extern int SafeWrite(int fd, const void *data, int len); extern int askForCredit(int fd, unsigned char socketID, int *sndSz, int *rcvSz); extern int writeData(int fd, unsigned char socketID, const unsigned char *buf, int len, int eoj); extern int readData(int fd, unsigned char socketID, unsigned char *buf, int len); -extern int readAnswer(int fd, unsigned char *buf, int len); +extern int writeAndReadData(int fd, unsigned char socketID, + const unsigned char *cmd, int cmd_len, int eoj, + unsigned char *buf, int len, int *sndSz, int *rcvSz, + int (*test)(const unsigned char *buf)); +extern int readAnswer(int fd, unsigned char *buf, int len, int allowExtra); extern void flushData(int fd, unsigned char socketID); extern void setDebug(int debug); diff --git a/src/escputil/escputil.c b/src/escputil/escputil.c index 3d7b65d..df65b46 100644 --- a/src/escputil/escputil.c +++ b/src/escputil/escputil.c @@ -1,5 +1,5 @@ /* - * "$Id: escputil.c,v 1.97 2008/10/29 00:10:42 easysw Exp $" + * "$Id: escputil.c,v 1.99 2008/12/21 18:35:43 rlk Exp $" * * Printer maintenance utility for EPSON Stylus (R) printers * @@ -279,6 +279,14 @@ initialize_print_cmd(int do_init) exit_packet_mode_old(do_init); } +static void +initialize_print_cmd_new(int do_init) +{ + bufpos = 0; + STP_DEBUG(fprintf(stderr, "Initialize print command (force new)\n")); + exit_packet_mode_old(do_init); +} + int main(int argc, char **argv) { @@ -539,7 +547,7 @@ read_from_printer(int fd, char *buf, int bufsize, int quiet) int retry = 100; #ifdef HAVE_FCNTL_H fcntl(fd, F_SETFL, - O_NONBLOCK | fcntl(fd, F_GETFL)); + O_NONBLOCK | (fcntl(fd, F_GETFL) & ~(O_RDONLY|O_WRONLY|O_RDWR))); #endif memset(buf, 0, bufsize); @@ -784,13 +792,32 @@ set_printer_model(void) the_printer_t = NULL; } +static int +test_for_di(const unsigned char *buf) +{ + return !(strncmp("di", (const char *)buf, 2) && + strncmp("@EJL ID", (const char *)buf, 7)); +} + +static int +test_for_st(const unsigned char *buf) +{ + return !(strncmp("st", (const char *)buf, 2) && + strncmp("@BDC ST", (const char *)buf, 7)); +} + +static int +test_for_ii(const unsigned char *buf) +{ + return !(strncmp("ii", (const char *)buf, 2) && + strncmp("@BDC PS", (const char *)buf, 7)); +} + static const stp_printer_t * initialize_printer(int quiet, int fail_if_not_found) { int packet_initialized = 0; int fd; - int credit; - int retry = 4; int tries = 0; int status; int forced_packet_mode = 0; @@ -847,38 +874,29 @@ initialize_printer(int quiet, int fail_if_not_found) if (forced_packet_mode || ((buf[3] == status) && (buf[6] == 0x7f))) { + /* + * NX100 looks like it's in D4 mode, but it doesn't really + * respond correctly. So we force it out of D4 mode and + * then back in to ensure that it's right. Trying to force + * it into D4 mode alone isn't good enough. + */ + initialize_print_cmd_new(0); + (void) SafeWrite(fd, printer_cmd, bufpos); + flushData(fd, (unsigned char) -1); + forced_packet_mode = !init_packet(fd, 1); STP_DEBUG(fprintf(stderr, "Printer in packet mode....\n")); packet_initialized = 1; isnew = 1; - - credit = askForCredit(fd, socket_id, &send_size, &receive_size); - if (credit < 0) - { - STP_DEBUG(fprintf(stderr, "Cannot get credit\n")); - return NULL; - } /* request status command */ - status = writeData(fd, socket_id, (const unsigned char*)"di\1\0\1", - 5, 1); + status = + writeAndReadData(fd, socket_id, (const unsigned char*)"di\1\0\1", + 5, 1, (unsigned char *) buf, 1023, + &send_size, &receive_size, &test_for_di); if (status <= 0) { fprintf(stderr, _("\nCannot write to %s: %s\n"), raw_device, strerror(errno)); - return NULL; - } - do - { - status = readData(fd, socket_id, (unsigned char*)buf, 1023); - STP_DEBUG(fprintf(stderr, "readData try %d status %d\n", - retry, status)); - if (status <= -1 ) - return NULL; - } - while ( (retry-- != 0) && strncmp("di", (char*)buf, 2) && - strncmp("@EJL ID", (char*)buf, 7)); - if (!retry) - { - STP_DEBUG(fprintf(stderr, "No retries left!\n")); + close(fd); return NULL; } } @@ -887,16 +905,16 @@ initialize_printer(int quiet, int fail_if_not_found) if (status > 0) { pos = strstr((char*)buf, "@EJL ID"); - STP_DEBUG(fprintf(stderr, "pos: %s\n", pos)); + STP_DEBUG(fprintf(stderr, "pos: %s\n", pos ? pos : "(null)")); if (pos) pos = strchr(pos, (int) ';'); - STP_DEBUG(fprintf(stderr, "pos: %s\n", pos)); + STP_DEBUG(fprintf(stderr, "pos: %s\n", pos ? pos : "(null)")); if (pos) pos = strchr(pos + 1, (int) ';'); - STP_DEBUG(fprintf(stderr, "pos: %s\n", pos)); + STP_DEBUG(fprintf(stderr, "pos: %s\n", pos ? pos : "(null)")); if (pos) pos = strchr(pos, (int) ':'); - STP_DEBUG(fprintf(stderr, "pos: %s\n", pos)); + STP_DEBUG(fprintf(stderr, "pos: %s\n", pos ? pos : "(null)")); if (pos) { spos = strchr(pos, (int) ';'); @@ -930,6 +948,7 @@ initialize_printer(int quiet, int fail_if_not_found) else { STP_DEBUG(fprintf(stderr, "Can't get response to @EJL ID\n")); + close(fd); return NULL; } } @@ -1232,6 +1251,9 @@ print_old_ink_levels(const char *ind, stp_string_list_t *color_list) static void do_old_status(status_cmd_t cmd, const char *buf, const stp_printer_t *printer) { + if (cmd == CMD_STATUS) + printf(_("Printer Name: %s\n"), + printer ? stp_printer_get_long_name(printer) : _("Unknown")); do { const char *ind; @@ -1374,7 +1396,6 @@ do_status_command_internal(status_cmd_t cmd) { int fd; int status; - int credit; int retry = 4; char buf[1024]; const stp_printer_t *printer; @@ -1407,33 +1428,15 @@ do_status_command_internal(status_cmd_t cmd) if (isnew) { - credit = askForCredit(fd, socket_id, &send_size, &receive_size); - if (credit < 0) - { - STP_DEBUG(fprintf(stderr, "\nCannot get credit\n")); - exit(1); - } /* request status command */ - status = writeData(fd, socket_id, (const unsigned char*)"st\1\0\1", - 5, 1); + status = + writeAndReadData(fd, socket_id, (const unsigned char*)"st\1\0\1", + 5, 1, (unsigned char *) buf, 1023, + &send_size, &receive_size, &test_for_st); if (status <= 0) { fprintf(stderr, _("\nCannot write to %s: %s\n"), raw_device, strerror(errno)); - exit(1); - } - do - { - status = readData(fd, socket_id, (unsigned char*)buf, 1023); - if (status < 0) - { - exit(1); - } - STP_DEBUG(fprintf(stderr, "readData try %d status %d\n", retry, status)); - } while ((retry-- != 0) && strncmp("st", buf, 2) && - strncmp("@BDC ST", buf, 7)); - /* "@BCD ST ST" found */ - if (!retry) - { + CloseChannel(fd, socket_id); exit(1); } buf[status] = '\0'; @@ -1482,8 +1485,6 @@ do_extended_ink_info(int extended_output) { int fd; int status; - int credit; - int retry = 4; char buf[1024]; unsigned val, id, id2, year, year2, month, month2; unsigned iv[6]; @@ -1533,16 +1534,11 @@ do_extended_ink_info(int extended_output) * message rather than from the ink list. This gives us a * last chance to determine the inks */ - credit = askForCredit(fd, socket_id, &send_size, &receive_size); - if (credit < 0) - { - stp_parameter_description_destroy(&desc); - STP_DEBUG(fprintf(stderr, "Cannot get credit\n")); - exit(1); - } /* request status command */ - status = writeData(fd, socket_id, (const unsigned char*)"st\1\0\1", - 5, 1); + status = + writeAndReadData(fd, socket_id, (const unsigned char*)"st\1\0\1", + 5, 1, (unsigned char *) buf, 1023, + &send_size, &receive_size, &test_for_st); if (status <= 0) { stp_parameter_description_destroy(&desc); @@ -1550,25 +1546,6 @@ do_extended_ink_info(int extended_output) raw_device, strerror(errno)); exit(1); } - do - { - status = readData(fd, socket_id, (unsigned char*)buf, 1023); - if (status < 0) - { - stp_parameter_description_destroy(&desc); - exit(1); - } - STP_DEBUG(fprintf(stderr, "readData try %d status %d\n", - retry, status)); - } - while ((retry-- != 0) && strncmp("st", buf, 2) && - strncmp("@BDC ST", buf, 7)); - /* "@BCD ST ST" found */ - if (!retry) - { - stp_parameter_description_destroy(&desc); - exit(1); - } buf[status] = '\0'; if ( buf[7] == '2' ) { @@ -1601,26 +1578,16 @@ do_extended_ink_info(int extended_output) for (i = 0; i < stp_string_list_count(color_list); i++) { char req[] = "ii\2\0\1\1"; - credit = askForCredit(fd, socket_id, &send_size, &receive_size); - if (credit < 0) - exit(1); req[5] = i + 1; - /* request status command */ - status = writeData(fd, socket_id, (const unsigned char*)req, 6, 1); + status = + writeAndReadData(fd, socket_id, (const unsigned char*)req, + 6, 1, (unsigned char *) buf, 1023, + &send_size, &receive_size, &test_for_ii); if (status <= 0) - exit(1); - retry = 4; - do { - status = readData(fd, socket_id, (unsigned char*) buf, 1023); - if (status < 0) - { - exit(1); - } - } while ((retry-- != 0) && strncmp("ii", buf, 2) && - strncmp("@BDC PS", buf, 7)); - if (!retry) /* couldn't read answer */ - exit(1); + CloseChannel(fd, socket_id); + exit(1); + } ind = strchr(buf, 'I'); if (!ind) printf("Cannot identify cartridge in slot %d\n", i); |