/******************************************************************************* isPrinterWorking ********************************************************************************/ static int isPrinterWorking(CNNLHANDLE h, const int retry, const unsigned long timeout){ char *buf; char buffer[512]; unsigned long readsz = 0; fprintf(stderr, "DEBUG: [cnijnetprn] IsPrinterWorking starts.\n"); CheckParentProcess(h); if (CNNL_GetDeviceID(h, buffer, &readsz, sizeof(buffer), 3, 6000) != CNNL_RET_SUCCESS){ return CNNL_RET_FAILURE; } else { buf = buffer+2; fprintf(stderr, "DEBUG: [cnijnetprn] DeviceID=[%s]\n", buf); if (getStatusCode((char *)buf, "STA:", "20", 1) == CNNL_RET_SUCCESS){ return CNNL_RET_NOT_WORKING; } } if (getPrinterStatus(h, buffer, sizeof(buffer)) < 0){ return CNNL_RET_FAILURE; } else { buf = buffer+2; // check wether job is cancelled by cancel button if (getStatusCode((char *)buf, "DJS:", "CC", 1) == CNNL_RET_SUCCESS){ mode |= CNNL_JOB_CANCELLED; return CNNL_RET_SUCCESS; } if (getStatusCode((char *)buf, "DJS:", "SC", 1) == CNNL_RET_SUCCESS){ mode |= CNNL_JOB_CANCELLED; return CNNL_RET_SUCCESS; } // check wether printer is work if (getStatusCode((char *)buf, "DBS:", "DS", 1) == CNNL_RET_SUCCESS) return CNNL_RET_NOT_WORKING; // check wether printer is poweroff if (getStatusCode((char *)buf, "DBS:", "SL", 1) == CNNL_RET_SUCCESS) return CNNL_RET_POWEROFF; if (getStatusCode((char *)buf, "DBS:", "SD", 1) == CNNL_RET_SUCCESS) return CNNL_RET_POWEROFF; // check wether printer is work if (getStatusCode((char *)buf, "DBS:", "NO", 1) != CNNL_RET_SUCCESS && getStatusCode((char *)buf, "DBS:", "UK", 1) != CNNL_RET_SUCCESS) return CNNL_RET_SUCCESS; // check pid if (getStatusCode((char *)buf, "PID:", "00", 2) != CNNL_RET_SUCCESS) return CNNL_RET_SUCCESS; // check doc if (getStatusCode((char *)buf, "DOC:", "NO", 3) != CNNL_RET_SUCCESS) return CNNL_RET_SUCCESS; // check dsc if (getStatusCode((char *)buf, "DSC:", "NO", 1) != CNNL_RET_SUCCESS) return CNNL_RET_SUCCESS; return CNNL_RET_NOT_WORKING; } }
/******************************************************************************* fread_with_retry ********************************************************************************/ unsigned long fread_with_retry(char *rbuffer, unsigned long bufsize, FILE *fp){ unsigned long d_time; fd_set fds; struct timeval timeout; int errorcount=0; while (!(mode & CNNL_JOB_CANCELLED) && !(mode & CNNL_JOB_ERROR)){ CheckParentProcess(hnd); timeout.tv_sec = 3; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(0,&fds); select(1,&fds,NULL,NULL,&timeout); if(FD_ISSET(0,&fds)){ size_t s = fread(rbuffer, sizeof(char), bufsize, fp); if (ferror(fp) == 0){ return (s * sizeof(char)); } else { mode |= CNNL_JOB_ERROR; return 0; } } else { // keep connection if (CNNL_GetTimeout(hnd, &d_time, 3, 6000) != CNNL_RET_SUCCESS){ if (errorcount > 10){ mode |= CNNL_JOB_ERROR; return 0; } else { errorcount++; } } else { errorcount=0; } } } return 0; }
/******************************************************************************* sendData ********************************************************************************/ int sendData(CNNLHANDLE hnd, void *buffer, unsigned long size, int sendmode, FILE *fp){ unsigned long wsize=0, res_size=0, req_size=0; int ret, status; time_t lastchecktime=0; while (!(mode & CNNL_JOB_ERROR) && !(mode & CNNL_JOB_CANCELLED) && wsize < size){ req_size = (size - wsize > packet_size)? packet_size: (size - wsize); ret = CNNL_DataWrite(hnd, buffer+wsize, req_size, &res_size, 5, 30000); if (ret == CNNL_RET_SUCCESS){ wsize += res_size; } else if (ret == CNNL_RET_FAILURE){ /* printing is failed */ return -1; } else { wsize += res_size; usleep(40*1000); } /* check power off */ if (time(NULL) - lastchecktime > 4){ if (sendmode != SEND_IVEC){ status = check_print(hnd, 1, 3000); if (status == CNNL_RET_POWEROFF){ mode |= CNNL_JOB_CANCELLED; return 0; } } lastchecktime = time(NULL); } usleep(40*1000); CheckParentProcess(hnd); } return 0; }
/******************************************************************************* _ij_network_print ********************************************************************************/ static int _ij_network_print( const char *macaddr, const char *user, const char *job, const char *model_number, const int is_direct, FILE *fp ){ int errcode = 0; char ipaddr[STRING_SHORT]; char hostname[HOST_NAME_MAX+1]; char library_path[512]; char *rbuffer = NULL; char *p = NULL; void *lib_handle = NULL; uint32_t len = 0; int working = 0; int count = 0; int tmp_ret = CNNL_RET_SUCCESS; // clear buffer setbuf(stdout, NULL); setbuf(stderr, NULL); memset(ipaddr, 0x00, STRING_SHORT); memset(hostname, 0x00, HOST_NAME_MAX+1); // allocate memory if ((rbuffer=(char*)malloc(sizeof(char)*READ_BUFFER_SIZE)) == NULL){ goto error_init; } // get hostname if (gethostname(hostname, HOST_NAME_MAX) != 0){ errcode = 1; fprintf(stderr, "ERROR: cannot get hostname\n"); goto error_init; } hostname[(HOST_NAME_MAX > 31)? 31:HOST_NAME_MAX] = 0; mode = CNNL_JOB_PREPARING; init_printing: /* write to printer */ { unsigned long latest_version = CNNL_LIB_LATEST_VERSION; unsigned long regacy_version = 100; unsigned long param_size = sizeof(unsigned long); /* Init */ if (CNNL_Init(&hnd) != CNNL_RET_SUCCESS){ errcode = 1; fprintf(stderr, "ERROR: error occurred while preparing(%d)\n", __LINE__); goto error_init; } if (CNNL_Config(hnd, CNNL_CONFIG_SET_VERSION, &latest_version, ¶m_size) != CNNL_RET_SUCCESS){ goto error_open; } /* --------------------------------------------------------------------- find printers */ { int i, j, found=0; fprintf(stderr, "INFO: \n"); for (i=0; !(mode & CNNL_JOB_CANCELLED); i++){ memset(ipaddr, 0x00, STRING_SHORT); if (CNNL_GetIPAddressEx(hnd, CACHE_PATH, macaddr, ipaddr, STRING_SHORT, CNNET_SEARCH_AUTO, 1, 5000) == CNNL_RET_SUCCESS){ found=1; break; } fprintf(stderr, "INFO: printer not responding; will retry in %d seconds...\n", WAITTIME_FIND_PRINTERS); for (j=0; j<WAITTIME_FIND_PRINTERS; j++, sleep(1)){ // cancelled if ((mode & CNNL_JOB_CANCELLED)) goto error_init; } fprintf(stderr, "INFO: \n"); } /* not found */ if (found == 0){ errcode = 1; fprintf(stderr, "ERROR: printer not found; job failed\n"); goto error_init; } /* cancelled */ if ((mode & CNNL_JOB_CANCELLED)) goto error_init; } fprintf(stderr, "INFO: \n"); /* --------------------------------------------------------------------- open printer */ if (CNNL_OpenEx(hnd, ipaddr, CNNET_TYPE_PRINTER, 10, 60000) != CNNL_RET_SUCCESS){ errcode = 1; fprintf(stderr, "ERROR: error occurred while preparing(%d)\n", __LINE__); goto error_open; } // check wether the printer exists or not if (CNNL_CheckVersion(hnd, 10, 60000) != CNNL_RET_SUCCESS){ errcode = 1; fprintf(stderr, "ERROR: error occurred while preparing(%d)\n", __LINE__); goto error_close; } // check command type if (CNNL_GetCommandType(hnd, &command, 10, 60000) != CNNL_RET_SUCCESS){ errcode = 1; fprintf(stderr, "ERROR: error occurred while preparing(%d)\n", __LINE__); goto error_close; } // switch functions if (command == CNNL_COMMAND_IVEC){ // support ivec commands start_print = CheckStartPrint; end_print = CheckEndPrint; check_print = CheckExecutePrint; memset(library_path, 0x00, sizeof(library_path)); snprintf(library_path, sizeof(library_path)-1, CNCL_LIB_PATH, model_number); // load functions lib_handle = dlopen(library_path, RTLD_LAZY); if (lib_handle == NULL){ fprintf(stderr, "ERROR: cannot load library(%d)\n", __LINE__); errcode = 1; goto error_close; } makePrintCommand = dlsym(lib_handle, "CNCL_MakePrintCommand"); if (dlerror() != NULL){ fprintf(stderr, "ERROR: cannot load function(%d)\n", __LINE__); errcode = 1; goto error_close; } checkPrintCommand = dlsym(lib_handle, "CNCL_CheckPrintCommand"); if (dlerror() != NULL){ fprintf(stderr, "ERROR: cannot load function(%d)\n", __LINE__); errcode = 1; goto error_close; } getStatusCommand = dlsym(lib_handle, "CNCL_GetStatusCommand"); if (dlerror() != NULL){ fprintf(stderr, "ERROR: cannot load function(%d)\n", __LINE__); errcode = 1; goto error_close; } } else { param_size = sizeof(unsigned long); if (CNNL_Config(hnd, CNNL_CONFIG_SET_VERSION, ®acy_version, ¶m_size) != CNNL_RET_SUCCESS){ goto error_close; } // not support ivec commands start_print = CNNL_StartPrint; end_print = CNNL_EndPrint; check_print = CNNL_CheckPrint; } packet_size = get_packet_size(hnd, atoi(model_number)); /* --------------------------------------------------------------------- start session */ mode = CNNL_JOB_WAITING; { int j=0, ret; if (!(mode & CNNL_JOB_CANCELLED)){ // if job is not cancelled while (!(mode & CNNL_JOB_CANCELLED)){ // request to start session if ((ret=CNNL_SessionStart(hnd, user, hostname, job, 3, 9000)) == CNNL_RET_SUCCESS){ // succeed to start session mode=CNNL_JOB_PRINTING; break; } // failed to start session if (ret == CNNL_RET_BUSY){ for (j=0; j<WAITTIME_START_SESSION; j++, sleep(1)){ // cancelled CheckParentProcess(hnd); if ((mode & CNNL_JOB_CANCELLED)) goto error_close; } } else { fprintf(stderr, "INFO: cannot start printing; will retry in %d seconds...\n", WAITTIME_RETRY_SEARCH); for (j=0; j<WAITTIME_RETRY_SEARCH; j++, sleep(1)){ // cancelled CheckParentProcess(hnd); if ((mode & CNNL_JOB_CANCELLED)) goto error_init; } CNNL_Close(hnd); CNNL_Terminate(&hnd); hnd = NULL; goto init_printing; } } } if ((mode & CNNL_JOB_CANCELLED)){ goto error_job_cancelled; } } fprintf(stderr, "INFO: \n"); /* set timeout */ CNNL_SetTimeout(hnd, SESSION_TIMEOUT, 3, 15000); /* start printing */ if (!(mode & CNNL_JOB_ERROR) && start_print(hnd, 3, 9000) != CNNL_RET_SUCCESS){ errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while preparing(%d)\n", __LINE__); goto error_printing; } /* --------------------------------------------------------------------- print(after this line, response error is fatal; job is canceled) */ /* send start command... */ if (is_direct == 0 && command == CNNL_COMMAND_IVEC){ // IVEC dispatchCommandIVEC(hnd, CNCL_COMMAND_POWERON); if (dispatchCommandIVEC(hnd, CNCL_COMMAND_START1) < 0){ errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_printing; } if (dispatchCommandIVEC(hnd, CNCL_COMMAND_START2) < 0){ errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_printing; } } else { // standard commands } /* send print data... */ { // waiting for print data... fprintf(stderr, "INFO: waiting print data ...\n"); len = fread_with_retry(rbuffer, READ_BUFFER_SIZE, fp); if ((mode & CNNL_JOB_ERROR)){ errcode = 1; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_close; } p = rbuffer; fprintf(stderr, "INFO: \n"); while (!(mode & CNNL_JOB_ERROR) && !(mode & CNNL_JOB_CANCELLED) && len > 0){ if (sendData(hnd, p, len, SEND_PRINT_DATA, fp) < 0){ errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_printing; } len = fread_with_retry(rbuffer, READ_BUFFER_SIZE, fp); p = rbuffer; // check if printer is working if (working != 1){ tmp_ret = check_print(hnd, 3, 9000); if (tmp_ret == CNNL_RET_SUCCESS) working = 1; } usleep(40*1000); } if ((mode & CNNL_JOB_CANCELLED)) goto error_job_cancelled; } /* send end command... */ if (is_direct == 0 && command == CNNL_COMMAND_IVEC){ if (dispatchCommandIVEC(hnd, CNCL_COMMAND_END) < 0){ errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_printing; } } /* wait until printer starts working (for utility) */ for (count=0; working!=1 && count<10; sleep(1)){ tmp_ret = check_print(hnd, 3, 6000); if (tmp_ret == CNNL_RET_SUCCESS){ break; } else if (tmp_ret == CNNL_RET_POWEROFF){ goto error_job_cancelled; } else { count++; } if ((mode & CNNL_JOB_CANCELLED)) goto error_job_cancelled; } /* wait until printer is idle */ if (!(mode & CNNL_JOB_ERROR) && end_print(hnd, 3, 9000) != CNNL_RET_SUCCESS){ // cannot get end of print errcode = 1; mode |= CNNL_JOB_ERROR; fprintf(stderr, "ERROR: error occurred while printing(%d)\n", __LINE__); goto error_printing; } /* --------------------------------------------------------------------- close printer */ error_job_cancelled: error_printing: if ((mode & CNNL_JOB_ERROR) || (mode & CNNL_JOB_CANCELLED)){ CNNL_SoftReset(hnd, 5, 30000); } CNNL_SessionEnd(hnd, 5, 30000); error_close: if (lib_handle != NULL) dlclose(lib_handle); CNNL_Close(hnd); error_open: CNNL_Terminate(&hnd); error_init: fprintf(stderr, "INFO: \n"); free(rbuffer); } // read buffer(flush) { unsigned char dummy; while (fread(&dummy, sizeof(unsigned char), 1, fp) > 0); } fflush(stdout); fflush(stderr); // wait for next job sleep(1); // clear error if job is cancelled if (mode & CNNL_JOB_CANCELLED) errcode = 0; return (errcode == 0)? 0: 1; }
/******************************************************************************* DispatchCommandIVEC ********************************************************************************/ int dispatchCommandIVEC(CNNLHANDLE hnd, int type){ char command_buffer[CNCL_MAKECOMMAND_BUF_LEN]; char read_buffer[4096]; static char job_id[16]; unsigned long timeout = 6000; int error_count=0; memset(command_buffer, 0x00, sizeof(command_buffer)); switch (type){ case CNCL_COMMAND_START1: memset(job_id, 0x00, sizeof(job_id)); if (makePrintCommand(type, command_buffer, sizeof(command_buffer), NULL, "1") != CNCL_OK){ return -1; } type = CNCL_CHECK_START1; break; case CNCL_COMMAND_START2: if (makePrintCommand(type, command_buffer, sizeof(command_buffer), job_id, NULL) != CNCL_OK){ return -1; } type = CNCL_CHECK_START2; break; case CNCL_COMMAND_END: if (makePrintCommand(type, command_buffer, sizeof(command_buffer), job_id, NULL) != CNCL_OK){ return -1; } type = CNCL_CHECK_END; break; case CNCL_COMMAND_POWERON: if (makePrintCommand(type, command_buffer, sizeof(command_buffer), NULL, "0") != CNCL_OK){ return -1; } type = CNCL_CHECK_POWERON; break; default: return -1; } /* send */ if (sendData(hnd, command_buffer, strlen(command_buffer), SEND_IVEC, NULL) < 0){ fprintf(stderr, "DEBUG: [cnijnetprn] dispatchCommandIVEC failed(%d)\n", __LINE__); return -1; } /* poweron command is not need to check response */ if (type == CNCL_CHECK_POWERON){ return 0; } /* receive */ while (!(mode & CNNL_JOB_ERROR) && !(mode & CNNL_JOB_CANCELLED)){ unsigned long rsize = 0; memset(read_buffer, 0x00, sizeof(read_buffer)); usleep(1000*1000); int result = CNNL_DataRead(hnd, read_buffer, &rsize, sizeof(read_buffer), 3, timeout); fprintf(stderr, "DEBUG: [cnijnetprn] dispatchCommandIVEC Receive(type=%d, result=%d, err=%d)\n", type, result, error_count); if (result == CNNL_RET_SUCCESS){ // check response if (checkPrintCommand(type, read_buffer, (short)rsize, job_id, sizeof(job_id)) == CNCL_OK){ // response status is OK return 0; } error_count = 0; } else if (result == CNNL_RET_BUSY_RESPONSE){ error_count = 0; } else { if (error_count >= 30){ fprintf(stderr, "DEBUG: [cnijnetprn] dispatchCommandIVEC failed(%d)\n", __LINE__); return -1; } else { error_count++; } } CheckParentProcess(hnd); } fprintf(stderr, "DEBUG: [cnijnetprn] dispatchCommandIVEC failed(%d)\n", __LINE__); return -1; }