From 879e6db06338166657609930768f76d8d7e7afbb Mon Sep 17 00:00:00 2001 From: Joe Nahmias Date: Fri, 7 Dec 2012 21:44:43 -0500 Subject: Imported Upstream version 1.2 --- bjnp-commands.c | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 bjnp-commands.c (limited to 'bjnp-commands.c') diff --git a/bjnp-commands.c b/bjnp-commands.c new file mode 100644 index 0000000..ede0a86 --- /dev/null +++ b/bjnp-commands.c @@ -0,0 +1,347 @@ +/* + * TCP/IP IO communication implementation for + * bjnp backend for the Common UNIX Printing System (CUPS). + * Copyright 2008 by Louis Lagendijk + * + * These coded instructions, statements, and computer programs are the + * property of Louis Lagendijk and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * Process bjnp commands + */ + +#include "bjnp.h" +#include "bjnp-protocol.h" +#include +#include + +static int serial = 0; +uint16_t session_id = 0; + +int +parse_status_to_paperout (int len, char *status_str) +{ +/* + * parses the status string of the printer to retrieve paper status + * of the printer + * Returns: BJNP_PAPER_OK = paper ok + * BJNP_PAPER_OUT = out of paper + * BJNP_PAPER_UNKNOWN = paper status not found + */ + + char s[BJNP_IEEE1284_MAX]; + char *tok; + unsigned int status; + + strcpy (s, status_str); + s[len] = '\0'; + + tok = strtok (s, ";"); + while (tok != NULL) + { + /* BST contains status */ + + if (strncmp (tok, STR_BST, strlen (STR_BST)) == 0) + { + if (sscanf (tok + 4, "%2x", &status) != 1) + { + bjnp_debug (LOG_WARN, "Could not parse paper status tag: %s!\n", + STR_BST); + return BJNP_PAPER_UNKNOWN; + } + else + { + bjnp_debug (LOG_DEBUG, + "Read printer status: %u\n Printing = %d\n Busy = %d\n PaperOut = %d\n", + status, ((status & BST_PRINTING) != 0), + ((status & BST_BUSY) != 0), + ((status & BST_OPCALL) != 0)); + if (status & BST_OPCALL) + { + bjnp_debug (LOG_INFO, "Paper out!\n"); + return BJNP_PAPER_OUT; + } + else + { + bjnp_debug (LOG_INFO, "Paper ok!\n"); + return BJNP_PAPER_OK; + } + } + } + tok = strtok (NULL, ";"); + } + return BJNP_PAPER_UNKNOWN; +} + +void +clear_cmd(bjnp_command_t * cmd) +{ + memset(cmd, 0, sizeof(*cmd) ); +} + +int +bjnp_set_command_header (bjnp_command_t *cmd, char cmd_code, int my_session_id, + int command_len) +{ + /* + * Set command buffer with command code, session_id and lenght of payload + * Returns: sequence number of command + */ + strncpy (cmd->header.BJNP_id, BJNP_STRING, sizeof (cmd->header.BJNP_id)); + cmd->header.dev_type = BJNP_CMD_PRINT; + cmd->header.cmd_code = cmd_code; + cmd->header.unknown1 = htons(0); + cmd->header.seq_no = htons (++serial); + cmd->header.session_id = htons (my_session_id); + + cmd->header.payload_len = htonl (command_len - bjnp_header_size); + + return serial; +} + + + +static int +bjnp_process_udp_command (http_addr_t * addr, bjnp_command_t *command, int cmd_len, bjnp_response_t *response) +{ + /* + * Send UDP command and retrieve response + * Returns: length of response or -1 in case of error + */ + + int sockfd; + int numbytes; + fd_set fdset; + struct timeval timeout; + int try; + char ipaddress[128]; + int port; + int size; + + get_address_info( addr, ipaddress, &port); + bjnp_debug (LOG_DEBUG, "Sending UDP command to %s port %d\n", + ipaddress, port ); + + if ((sockfd = socket (get_protocol_family( addr), SOCK_DGRAM, 0)) == -1) + { + bjnp_debug (LOG_CRIT, "bjnp_process_udp_command: sockfd - %s\n", strerror (errno)); + return -1; + } + + size = sa_size(addr); + if (connect (sockfd, &(addr->addr), (socklen_t) size ) + != 0) + { + bjnp_debug (LOG_CRIT, "bjnp_process_udp_command: connect - %s\n", strerror (errno)); + close( sockfd); + return -1; + } + + for (try = 0; try < 3; try++) + { + if ((numbytes = send (sockfd, command, cmd_len, 0)) != cmd_len) + { + bjnp_debug (LOG_CRIT, "bjnp_process_udp_command: Sent only %d bytes of packet", + numbytes); + } + + + FD_ZERO (&fdset); + FD_SET (sockfd, &fdset); + timeout.tv_sec = 3; + timeout.tv_usec = 0; + + if (select (sockfd + 1, &fdset, NULL, NULL, &timeout) <= 0) + { + /* no data recieved OR error, in either case retry */ + continue; + } + + if ((numbytes = recv (sockfd, response, sizeof(*response), MSG_WAITALL)) == -1) + { + bjnp_debug (LOG_CRIT, "bjnp_process_udp_command: no data received (recv)"); + continue; + } + close (sockfd); + return numbytes; + } + /* max tries reached, return failure */ + close (sockfd); + return -1; +} + +int +get_printer_id (http_addr_t * addr, char *model, char *IEEE1284_id) +{ + /* + * get printer identity + * Sets model (make and model) and IEEE1284_id + */ + + bjnp_command_t cmd; + bjnp_response_t id; + char printer_id[BJNP_IEEE1284_MAX]; + int resp_len; + int id_len; + int min_size; + + /* set defaults */ + + strcpy (model, "Unidentified printer"); + strcpy (IEEE1284_id, ""); + + clear_cmd(&cmd); + bjnp_set_command_header (&cmd, CMD_UDP_GET_ID, 0, sizeof(cmd.udp_get_id) ); + + bjnp_hexdump (LOG_DEBUG2, "Get printer identity", (char *) &cmd, + sizeof (cmd.udp_get_id)); + + resp_len = + bjnp_process_udp_command (addr, &cmd, sizeof (cmd.udp_get_id), + &id); + + min_size = bjnp_header_size + sizeof( id.udp_identity_response.id_len); + if ( resp_len <= min_size ) + { + return -1; + } + + bjnp_hexdump (LOG_DEBUG2, "Printer identity:", &id, resp_len); + + id_len = ntohs (id.udp_identity_response.id_len) - sizeof (id.udp_identity_response.id_len); + + if ( (id_len < 0) || (id_len > (resp_len - bjnp_header_size) ) || ( id_len > BJNP_IEEE1284_MAX) ) + { + bjnp_debug( LOG_DEBUG, "Id - length recieved is invalid: %d (total response length = %d\n", + id_len, resp_len); + return -1; + } + + /* set IEEE1284_id */ + + strncpy (printer_id, id.udp_identity_response.id, id_len); + printer_id[id_len] = '\0'; + + bjnp_debug (LOG_INFO, "Identity = %s\n", printer_id); + + if (IEEE1284_id != NULL) + strcpy (IEEE1284_id, printer_id); + + /* get make&model from IEEE1284 id */ + + if (model != NULL) + { + parse_IEEE1284_to_model (printer_id, model); + bjnp_debug (LOG_DEBUG, "Printer model = %s\n", model); + } + return 0; +} + +bjnp_paper_status_t +bjnp_get_paper_status (http_addr_t * addr) +{ + /* + * get printer paper status + */ + + bjnp_command_t cmd; + bjnp_response_t response; + int resp_len; + + /* set defaults */ + + clear_cmd(&cmd); + bjnp_set_command_header (&cmd, CMD_UDP_GET_STATUS, 0, sizeof(cmd.udp_get_status) ); + + bjnp_hexdump (LOG_DEBUG2, "Get printer status", (char *) &cmd, + sizeof (cmd.udp_get_status)); + + resp_len = + bjnp_process_udp_command (addr, &cmd, sizeof (cmd.udp_get_status), + &response); + + if (resp_len <= 0) + return BJNP_PAPER_UNKNOWN; + + bjnp_hexdump (LOG_DEBUG2, "Printer status:", &response, resp_len); + + return parse_status_to_paperout ( ntohs(response.udp_status_response.status_len), response.udp_status_response.status); + +} + +int bjnp_send_job_details (http_addr_t *addr, char *user, char *title ) +{ +/* + * send details of printjob to printer + * Returns: 0 = ok, -1 = error + */ + + char hostname[BJNP_HOST_MAX]; + int resp_len; + bjnp_command_t cmd; + bjnp_response_t resp; + + /* send job details command */ + + clear_cmd(&cmd); + bjnp_set_command_header (&cmd, CMD_UDP_PRINT_JOB_DET, 0, + sizeof (cmd.udp_job_details) ); + + /* create payload */ + + gethostname (hostname, BJNP_HOST_MAX - 1); + + charTo2byte (cmd.udp_job_details.unknown, "", sizeof (cmd.udp_job_details.unknown)); + charTo2byte (cmd.udp_job_details.hostname, hostname, sizeof (cmd.udp_job_details.hostname)); + charTo2byte (cmd.udp_job_details.username, user, sizeof (cmd.udp_job_details.username)); + charTo2byte (cmd.udp_job_details.jobtitle, title, sizeof (cmd.udp_job_details)); + + bjnp_hexdump (LOG_DEBUG2, "Job details", &cmd, + sizeof(cmd.udp_job_details)); + resp_len = bjnp_process_udp_command (addr, &cmd, sizeof(cmd.udp_job_details), &resp); + + if (resp_len > 0) + { + bjnp_hexdump (LOG_DEBUG2, "Job details response:", &resp, + resp_len); + session_id = ntohs (resp.udp_print_job_details_response.header.session_id); + return 0; + } + return -1; +} + +int bjnp_send_close( http_addr_t *addr) +{ +/* + * Signal end of printjob to printer + */ + + int resp_len; + bjnp_command_t cmd; + bjnp_response_t resp; + + clear_cmd(&cmd); + bjnp_set_command_header (&cmd, CMD_UDP_CLOSE, session_id, sizeof(cmd.udp_close) ); + + bjnp_hexdump (LOG_DEBUG2, "bjnp_send_close", (char *) &cmd, + sizeof( cmd.udp_close)); + resp_len = + bjnp_process_udp_command (addr, &cmd, sizeof (cmd.udp_close), + &resp); + + if (resp_len != sizeof (resp.udp_close_response)) + { + bjnp_debug (LOG_CRIT, + "Received %d characters in close response, expected %d\n", + resp_len, sizeof (resp.udp_close_response)); + return -1; + } + bjnp_hexdump (LOG_DEBUG2, "Finish printjob response", &resp, resp_len); + return 0; +} + -- cgit v1.2.3