3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2003-2010 Marcel Holtmann <marcel@holtmann.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include <sys/socket.h>
34 #include <netinet/in.h>
36 #include "lib/bluetooth.h"
37 #include "lib/l2cap.h"
39 #include "lib/sdp_lib.h"
43 #define HCRP_PDU_CREDIT_GRANT 0x0001
44 #define HCRP_PDU_CREDIT_REQUEST 0x0002
45 #define HCRP_PDU_GET_LPT_STATUS 0x0005
47 #define HCRP_STATUS_FEATURE_UNSUPPORTED 0x0000
48 #define HCRP_STATUS_SUCCESS 0x0001
49 #define HCRP_STATUS_CREDIT_SYNC_ERROR 0x0002
50 #define HCRP_STATUS_GENERIC_FAILURE 0xffff
56 } __attribute__ ((packed));
57 #define HCRP_PDU_HDR_SIZE 6
59 struct hcrp_credit_grant_cp {
61 } __attribute__ ((packed));
62 #define HCRP_CREDIT_GRANT_CP_SIZE 4
64 struct hcrp_credit_grant_rp {
66 } __attribute__ ((packed));
67 #define HCRP_CREDIT_GRANT_RP_SIZE 2
69 struct hcrp_credit_request_rp {
72 } __attribute__ ((packed));
73 #define HCRP_CREDIT_REQUEST_RP_SIZE 6
75 struct hcrp_get_lpt_status_rp {
78 } __attribute__ ((packed));
79 #define HCRP_GET_LPT_STATUS_RP_SIZE 3
81 static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
83 struct hcrp_pdu_hdr hdr;
84 struct hcrp_credit_grant_cp cp;
85 struct hcrp_credit_grant_rp rp;
86 unsigned char buf[128];
89 hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
91 hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
93 memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
94 memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
95 len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
99 len = read(sk, buf, sizeof(buf));
103 memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
104 memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
106 if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
114 static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
116 struct hcrp_pdu_hdr hdr;
117 struct hcrp_credit_request_rp rp;
118 unsigned char buf[128];
121 hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
122 hdr.tid = htons(tid);
124 memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
125 len = write(sk, buf, HCRP_PDU_HDR_SIZE);
129 len = read(sk, buf, sizeof(buf));
133 memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
134 memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
136 if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
142 *credit = ntohl(rp.credit);
147 static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
149 struct hcrp_pdu_hdr hdr;
150 struct hcrp_get_lpt_status_rp rp;
151 unsigned char buf[128];
154 hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
155 hdr.tid = htons(tid);
157 memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
158 len = write(sk, buf, HCRP_PDU_HDR_SIZE);
162 len = read(sk, buf, sizeof(buf));
166 memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
167 memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
169 if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
175 *lpt_status = rp.lpt_status;
180 static inline int hcrp_get_next_tid(int tid)
188 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)
190 struct sockaddr_l2 addr;
191 struct l2cap_options opts;
193 unsigned char buf[2048];
194 int i, ctrl_sk, data_sk, count, len, timeout = 0;
198 uint32_t tmp, credit = 0;
200 if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
201 perror("ERROR: Can't create socket");
203 return CUPS_BACKEND_FAILED;
205 return CUPS_BACKEND_RETRY;
208 memset(&addr, 0, sizeof(addr));
209 addr.l2_family = AF_BLUETOOTH;
210 bacpy(&addr.l2_bdaddr, src);
212 if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
213 perror("ERROR: Can't bind socket");
216 return CUPS_BACKEND_FAILED;
218 return CUPS_BACKEND_RETRY;
221 memset(&addr, 0, sizeof(addr));
222 addr.l2_family = AF_BLUETOOTH;
223 bacpy(&addr.l2_bdaddr, dst);
224 addr.l2_psm = htobs(ctrl_psm);
226 if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
227 perror("ERROR: Can't connect to device");
230 return CUPS_BACKEND_FAILED;
232 return CUPS_BACKEND_RETRY;
235 if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
236 perror("ERROR: Can't create socket");
239 return CUPS_BACKEND_FAILED;
241 return CUPS_BACKEND_RETRY;
244 memset(&addr, 0, sizeof(addr));
245 addr.l2_family = AF_BLUETOOTH;
246 bacpy(&addr.l2_bdaddr, src);
248 if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
249 perror("ERROR: Can't bind socket");
253 return CUPS_BACKEND_FAILED;
255 return CUPS_BACKEND_RETRY;
258 memset(&addr, 0, sizeof(addr));
259 addr.l2_family = AF_BLUETOOTH;
260 bacpy(&addr.l2_bdaddr, dst);
261 addr.l2_psm = htobs(data_psm);
263 if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
264 perror("ERROR: Can't connect to device");
268 return CUPS_BACKEND_FAILED;
270 return CUPS_BACKEND_RETRY;
273 fputs("STATE: -connecting-to-device\n", stderr);
275 memset(&opts, 0, sizeof(opts));
278 if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
279 perror("ERROR: Can't get socket options");
283 return CUPS_BACKEND_FAILED;
285 return CUPS_BACKEND_RETRY;
290 /* Ignore SIGTERM signals if printing from stdin */
293 sigset(SIGTERM, SIG_IGN);
294 #elif defined(HAVE_SIGACTION)
295 memset(&action, 0, sizeof(action));
296 sigemptyset(&action.sa_mask);
297 action.sa_handler = SIG_IGN;
298 sigaction(SIGTERM, &action, NULL);
300 signal(SIGTERM, SIG_IGN);
301 #endif /* HAVE_SIGSET */
304 tid = hcrp_get_next_tid(tid);
305 if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
306 fprintf(stderr, "ERROR: Can't grant initial credits\n");
310 return CUPS_BACKEND_FAILED;
312 return CUPS_BACKEND_RETRY;
315 for (i = 0; i < copies; i++) {
318 fprintf(stderr, "PAGE: 1 1\n");
319 lseek(fd, 0, SEEK_SET);
324 tid = hcrp_get_next_tid(tid);
325 if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
332 if (timeout++ > 300) {
333 tid = hcrp_get_next_tid(tid);
334 if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
335 fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
343 count = read(fd, buf, (credit > mtu) ? mtu : credit);
347 len = write(data_sk, buf, count);
349 perror("ERROR: Error writing to device");
352 return CUPS_BACKEND_FAILED;
356 fprintf(stderr, "ERROR: Can't send complete data\n");
366 return CUPS_BACKEND_OK;