summaryrefslogtreecommitdiffstats
path: root/cups
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-03-14 14:21:01 +0000
committerMarcel Holtmann <marcel@holtmann.org>2008-03-14 14:21:01 +0000
commita71ed7ebdf0599e0a019c9087669a62e026109a2 (patch)
treea805fba870d310e6ea3e09746757f91d68379bbe /cups
parent2168a48f8f05562fcd51f17744ead7d1c48e910f (diff)
Add CLASS support and retry on unavailable printers
Diffstat (limited to 'cups')
-rw-r--r--cups/Makefile.am2
-rw-r--r--cups/cups.h32
-rw-r--r--cups/hcrp.c48
-rw-r--r--cups/main.c50
-rw-r--r--cups/spp.c23
5 files changed, 120 insertions, 35 deletions
diff --git a/cups/Makefile.am b/cups/Makefile.am
index 8cd3d4d4..853c436d 100644
--- a/cups/Makefile.am
+++ b/cups/Makefile.am
@@ -4,7 +4,7 @@ cupsdir = $(libdir)/cups/backend
cups_PROGRAMS = bluetooth
-bluetooth_SOURCES = main.c sdp.c spp.c hcrp.c
+bluetooth_SOURCES = main.c cups.h sdp.c spp.c hcrp.c
bluetooth_LDADD = $(top_builddir)/common/libhelper.a \
@DBUS_LIBS@ @GLIB_LIBS@ @BLUEZ_LIBS@
diff --git a/cups/cups.h b/cups/cups.h
new file mode 100644
index 00000000..c8de4ab8
--- /dev/null
+++ b/cups/cups.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum { /**** Backend exit codes ****/
+ CUPS_BACKEND_OK = 0, /* Job completed successfully */
+ CUPS_BACKEND_FAILED = 1, /* Job failed, use error-policy */
+ CUPS_BACKEND_AUTH_REQUIRED = 2, /* Job failed, authentication required */
+ CUPS_BACKEND_HOLD = 3, /* Job failed, hold job */
+ CUPS_BACKEND_STOP = 4, /* Job failed, stop queue */
+ CUPS_BACKEND_CANCEL = 5, /* Job failed, cancel job */
+ CUPS_BACKEND_RETRY = 6, /* Failure requires us to retry (BlueZ specific) */
+};
diff --git a/cups/hcrp.c b/cups/hcrp.c
index 468e89fb..5f0211e2 100644
--- a/cups/hcrp.c
+++ b/cups/hcrp.c
@@ -37,6 +37,8 @@
#include <netinet/in.h>
+#include "cups.h"
+
#define HCRP_PDU_CREDIT_GRANT 0x0001
#define HCRP_PDU_CREDIT_REQUEST 0x0002
#define HCRP_PDU_GET_LPT_STATUS 0x0005
@@ -167,7 +169,7 @@ static inline int hcrp_get_next_tid(int tid)
return tid + 1;
}
-int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies)
+int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class)
{
struct sockaddr_l2 addr;
struct l2cap_options opts;
@@ -180,7 +182,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
perror("ERROR: Can't create socket");
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
memset(&addr, 0, sizeof(addr));
@@ -190,7 +195,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("ERROR: Can't bind socket");
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
memset(&addr, 0, sizeof(addr));
@@ -201,13 +209,19 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("ERROR: Can't connect to device");
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
perror("ERROR: Can't create socket");
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
memset(&addr, 0, sizeof(addr));
@@ -218,7 +232,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
perror("ERROR: Can't bind socket");
close(data_sk);
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
memset(&addr, 0, sizeof(addr));
@@ -230,7 +247,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
perror("ERROR: Can't connect to device");
close(data_sk);
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
fputs("STATE: -connecting-to-device\n", stderr);
@@ -242,7 +262,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
perror("ERROR: Can't get socket options");
close(data_sk);
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
mtu = opts.omtu;
@@ -266,7 +289,10 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
fprintf(stderr, "ERROR: Can't grant initial credits\n");
close(data_sk);
close(ctrl_sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
for (i = 0; i < copies; i++) {
@@ -306,7 +332,7 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
perror("ERROR: Error writing to device");
close(data_sk);
close(ctrl_sk);
- return 1;
+ return CUPS_BACKEND_FAILED;
}
if (len != count)
@@ -320,5 +346,5 @@ int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned s
close(data_sk);
close(ctrl_sk);
- return 0;
+ return CUPS_BACKEND_OK;
}
diff --git a/cups/main.c b/cups/main.c
index 629295b4..ac77e85d 100644
--- a/cups/main.c
+++ b/cups/main.c
@@ -40,23 +40,15 @@
#include <glib.h>
+#include "cups.h"
#include "dbus.h"
#include "sdp-xml.h"
-enum { /**** Backend exit codes ****/
- CUPS_BACKEND_OK = 0, /* Job completed successfully */
- CUPS_BACKEND_FAILED = 1, /* Job failed, use error-policy */
- CUPS_BACKEND_AUTH_REQUIRED = 2, /* Job failed, authentication required */
- CUPS_BACKEND_HOLD = 3, /* Job failed, hold job */
- CUPS_BACKEND_STOP = 4, /* Job failed, stop queue */
- CUPS_BACKEND_CANCEL = 5 /* Job failed, cancel job */
-};
-
extern int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
extern int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);
-extern int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies);
-extern int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies);
+extern int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);
+extern int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);
#define PRINTER_SERVICE_CLASS_NAME "printer"
@@ -563,7 +555,7 @@ int main(int argc, char *argv[])
unsigned short ctrl_psm, data_psm;
uint8_t channel, b[6];
char *ptr, str[3], device[18], service[12];
- const char *uri;
+ const char *uri, *cups_class;
int i, err, fd, copies, proto;
/* Make sure status messages are not buffered */
@@ -638,11 +630,15 @@ int main(int argc, char *argv[])
proto = 0;
}
- fprintf(stderr, "DEBUG: %s device %s service %s fd %d copies %d\n",
- argv[0], device, service, fd, copies);
+ cups_class = getenv("CLASS");
+
+ fprintf(stderr, "DEBUG: %s device %s service %s fd %d copies %d class %s\n",
+ argv[0], device, service, fd, copies,
+ cups_class ? cups_class : "(none)");
fputs("STATE: +connecting-to-device\n", stderr);
+service_search:
sdp = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
if (!sdp) {
fprintf(stderr, "ERROR: Can't open Bluetooth connection\n");
@@ -669,16 +665,26 @@ int main(int argc, char *argv[])
sdp_close(sdp);
if (err) {
+ if (cups_class) {
+ fputs("INFO: Unable to contact printer, queuing on "
+ "next printer in class...\n", stderr);
+ sleep(5);
+ return CUPS_BACKEND_FAILED;
+ }
+ sleep(20);
fprintf(stderr, "ERROR: Can't get service information\n");
- return CUPS_BACKEND_FAILED;
+ goto service_search;
}
+connect:
switch (proto) {
case 1:
- err = spp_print(BDADDR_ANY, &bdaddr, channel, fd, copies);
+ err = spp_print(BDADDR_ANY, &bdaddr, channel,
+ fd, copies, cups_class);
break;
case 2:
- err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm, fd, copies);
+ err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm,
+ fd, copies, cups_class);
break;
default:
err = CUPS_BACKEND_FAILED;
@@ -686,6 +692,16 @@ int main(int argc, char *argv[])
break;
}
+ if (err == CUPS_BACKEND_FAILED && cups_class) {
+ fputs("INFO: Unable to contact printer, queuing on "
+ "next printer in class...\n", stderr);
+ sleep(5);
+ return CUPS_BACKEND_FAILED;
+ } else if (err == CUPS_BACKEND_RETRY) {
+ sleep(20);
+ goto connect;
+ }
+
if (fd != 0)
close(fd);
diff --git a/cups/spp.c b/cups/spp.c
index 8bb9c1dc..cd9bfd58 100644
--- a/cups/spp.c
+++ b/cups/spp.c
@@ -34,7 +34,9 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
-int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
+#include "cups.h"
+
+int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class)
{
struct sockaddr_rc addr;
unsigned char buf[2048];
@@ -42,7 +44,10 @@ int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
if ((sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
perror("ERROR: Can't create socket");
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
addr.rc_family = AF_BLUETOOTH;
@@ -52,7 +57,10 @@ int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("ERROR: Can't bind socket");
close(sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
addr.rc_family = AF_BLUETOOTH;
@@ -62,7 +70,10 @@ int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("ERROR: Can't connect to device");
close(sk);
- return 1;
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
}
fputs("STATE: -connecting-to-device\n", stderr);
@@ -93,7 +104,7 @@ int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
if (err < 0) {
perror("ERROR: Error writing to device");
close(sk);
- return 1;
+ return CUPS_BACKEND_FAILED;
}
}
@@ -101,5 +112,5 @@ int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies)
close(sk);
- return 0;
+ return CUPS_BACKEND_OK;
}