/* * Photo Image Print System * Copyright (C) 2001-2004 EPSON KOWA Corporation. * Copyright (C) SEIKO EPSON CORPORATION 2001-2004. * * This file is part of the `ekpd' program. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * As a special exception, EPSON KOWA Corporation gives permission * to link the code of this program with the `cbt' library and * distribute linked combinations including the two. You must obey * the GNU General Public License in all respects for all of the * code used other then `cbt'. */ /* * Restrictions * Cannot be connected to more than one printer at a time. */ /* * Communication packet specification between client programs. * * [ input packet ] * header (3byte) : 'pcp' length data * length (2byte) : Size of data * data : Data (command) * * [ output packet ] * header (3byte) : 'pcp' length data * length (2byte) : Size of data. When it was 0, show that error * occurred with the server side. In that event * data size is always 1 (error code). * * error code * 0x00 No error (Nothing reply) * 0x01 Receive indistinct packet * 0x02 Cannot communicate with a printer * 0x03 Memory shortage */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include "cbtd.h" #include "libcbt.h" #include "cbtd_thread.h" static void cbtd_control (void); static int prt_connect (char*, P_CBTD_INFO); static void init_cbtd (P_CBTD_INFO); static int init_epson_cbt (P_CBTD_INFO); /* Default patamaters */ const char Device_Path[] = "/dev/lp0"; /* device driver */ const char Fifo_Path[] = "/var/ekpd/ekplp0"; /* fifo */ const int Socket_Port = 35586; /* port number */ int main (int argc, char* argv[]) { #ifndef _DEBUG int pid; if (geteuid () != 0) { fprintf (stderr, "must run as root\n"); return 1; } /* shift to daemon process */ if ((pid = fork ())) { exit (0); } if (pid < 0) { perror ("fork() failtd"); return 1; } #endif cbtd_control (); return 0; } /* main thread */ static void cbtd_control (void) { CBTD_INFO info; int set_flags, reset_flags; init_cbtd (&info); sig_set (); while (!is_sysflags (&info, ST_SYS_DOWN)) { for (;;) { set_flags = 0; reset_flags = ST_SYS_DOWN | ST_CLIENT_CONNECT | ST_JOB_PRINTING | ST_JOB_CANCEL; if (wait_sysflags (&info, set_flags, reset_flags, 5, WAIT_SYS_AND) == 0) break; if (is_sysflags (&info, ST_DAEMON_WAKEUP)) reset_sysflags (&info, ST_DAEMON_WAKEUP); } set_sysflags (&info, ST_DAEMON_WAKEUP); /* connect a printer */ if (prt_connect (info.devprt_path, &info) < 0) continue; /* initialize communication */ if (init_epson_cbt (&info) == 0) { /* thread starting */ set_sysflags (&info, ST_PRT_CONNECT); /* check status */ for (;;) { set_flags = ST_CLIENT_CONNECT | ST_JOB_PRINTING | ST_JOB_CANCEL; reset_flags = 0; if (wait_sysflags (&info, set_flags, reset_flags, 2, WAIT_SYS_OR) == 0) break; set_flags = ST_PRT_CONNECT; reset_flags = ST_SYS_DOWN; if (wait_sysflags (&info, set_flags, reset_flags, 2, WAIT_SYS_AND) == 0) break; } } end_epson_cbt (&info); if (info.devfd >= 0) { close (info.devfd); _DEBUG_MESSAGE("deconnect printer\n"); info.devfd = -1; if (!is_sysflags (&info, ST_SYS_DOWN)) sleep (2); } } /* wait for end of other thread */ while (info.datatrans_thread_status != THREAD_DOWN || info.comserv_thread_status != THREAD_DOWN) sleep (1); end_cbtd (&info); return; } /* connect a printer */ static int prt_connect (char* devprt_path, P_CBTD_INFO p_info) { int *fd = &p_info->devfd; int i; if (is_sysflags (p_info, ST_SYS_DOWN)) return -1; for (i = 0; i < 5; i++) { *fd = open (devprt_path, O_RDWR); if (*fd < 0) { usleep (500000); } else { _DEBUG_MESSAGE("connect printer\n"); return *fd; } } _DEBUG_FUNC(perror (devprt_path)); _DEBUG_MESSAGE("waiting.....\n"); sleep (3); return *fd; } /* initialize process */ static void init_cbtd (P_CBTD_INFO p_info) { memset (p_info, 0, sizeof (CBTD_INFO)); if (parameter_setup (p_info)) { /* default setup */ strcpy (p_info->devprt_path, Device_Path); strcpy (p_info->infifo_path, Fifo_Path); p_info->comsock_port = Socket_Port; } p_info->devfd = -1; p_info->sysflags = 0; p_info->sysflags_critical = init_critical (); p_info->ecbt_accsess_critical = init_critical (); assert (p_info->sysflags_critical != NULL && p_info->ecbt_accsess_critical != NULL); p_info->datatrans_thread_status = THREAD_RUN; p_info->comserv_thread_status = THREAD_RUN; p_info->datatrans_thread = init_thread (CBTD_THREAD_STACK_SIZE, (void *)datatrans_thread, (void *)p_info); p_info->comserv_thread = init_thread (CBTD_THREAD_STACK_SIZE, (void *)comserv_thread, (void *)p_info); assert (p_info->datatrans_thread != NULL && p_info->comserv_thread != NULL); return; } /* end of process */ void end_cbtd (P_CBTD_INFO p_info) { if (p_info->datatrans_thread) delete_thread (p_info->datatrans_thread); if (p_info->comserv_thread) delete_thread (p_info->comserv_thread); if (p_info->sysflags_critical) delete_critical (p_info->sysflags_critical); if (p_info->ecbt_accsess_critical) delete_critical (p_info->ecbt_accsess_critical); return; } /* initialize CBT */ static int init_epson_cbt (P_CBTD_INFO p_info) { start_ecbt_engine (); return open_port_driver (p_info); } /* end of CBT */ int end_epson_cbt (P_CBTD_INFO p_info) { int err = 0; err = close_port_driver (p_info); end_ecbt_engine (); return err; } #ifdef __FreeBSD__ void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) { abort(); } #endif