• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2003-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <signal.h>
33 #include <sys/socket.h>
34 
35 #include <bluetooth/bluetooth.h>
36 #include <bluetooth/l2cap.h>
37 #include <bluetooth/sdp.h>
38 #include <bluetooth/sdp_lib.h>
39 
40 #include <netinet/in.h>
41 
42 #include "cups.h"
43 
44 #define HCRP_PDU_CREDIT_GRANT		0x0001
45 #define HCRP_PDU_CREDIT_REQUEST		0x0002
46 #define HCRP_PDU_GET_LPT_STATUS		0x0005
47 
48 #define HCRP_STATUS_FEATURE_UNSUPPORTED	0x0000
49 #define HCRP_STATUS_SUCCESS		0x0001
50 #define HCRP_STATUS_CREDIT_SYNC_ERROR	0x0002
51 #define HCRP_STATUS_GENERIC_FAILURE	0xffff
52 
53 struct hcrp_pdu_hdr {
54 	uint16_t pid;
55 	uint16_t tid;
56 	uint16_t plen;
57 } __attribute__ ((packed));
58 #define HCRP_PDU_HDR_SIZE 6
59 
60 struct hcrp_credit_grant_cp {
61 	uint32_t credit;
62 } __attribute__ ((packed));
63 #define HCRP_CREDIT_GRANT_CP_SIZE 4
64 
65 struct hcrp_credit_grant_rp {
66 	uint16_t status;
67 } __attribute__ ((packed));
68 #define HCRP_CREDIT_GRANT_RP_SIZE 2
69 
70 struct hcrp_credit_request_rp {
71 	uint16_t status;
72 	uint32_t credit;
73 } __attribute__ ((packed));
74 #define HCRP_CREDIT_REQUEST_RP_SIZE 6
75 
76 struct hcrp_get_lpt_status_rp {
77 	uint16_t status;
78 	uint8_t  lpt_status;
79 } __attribute__ ((packed));
80 #define HCRP_GET_LPT_STATUS_RP_SIZE 3
81 
hcrp_credit_grant(int sk,uint16_t tid,uint32_t credit)82 static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
83 {
84 	struct hcrp_pdu_hdr hdr;
85 	struct hcrp_credit_grant_cp cp;
86 	struct hcrp_credit_grant_rp rp;
87 	unsigned char buf[128];
88 	int len;
89 
90 	hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
91 	hdr.tid = htons(tid);
92 	hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
93 	cp.credit = credit;
94 	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
95 	memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
96 	len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
97 	if (len < 0)
98 		return len;
99 
100 	len = read(sk, buf, sizeof(buf));
101 	if (len < 0)
102 		return len;
103 
104 	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
105 	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
106 
107 	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
108 		errno = EIO;
109 		return -1;
110 	}
111 
112 	return 0;
113 }
114 
hcrp_credit_request(int sk,uint16_t tid,uint32_t * credit)115 static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
116 {
117 	struct hcrp_pdu_hdr hdr;
118 	struct hcrp_credit_request_rp rp;
119 	unsigned char buf[128];
120 	int len;
121 
122 	hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
123 	hdr.tid = htons(tid);
124 	hdr.plen = htons(0);
125 	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
126 	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
127 	if (len < 0)
128 		return len;
129 
130 	len = read(sk, buf, sizeof(buf));
131 	if (len < 0)
132 		return len;
133 
134 	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
135 	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
136 
137 	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
138 		errno = EIO;
139 		return -1;
140 	}
141 
142 	if (credit)
143 		*credit = ntohl(rp.credit);
144 
145 	return 0;
146 }
147 
hcrp_get_lpt_status(int sk,uint16_t tid,uint8_t * lpt_status)148 static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
149 {
150 	struct hcrp_pdu_hdr hdr;
151 	struct hcrp_get_lpt_status_rp rp;
152 	unsigned char buf[128];
153 	int len;
154 
155 	hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
156 	hdr.tid = htons(tid);
157 	hdr.plen = htons(0);
158 	memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
159 	len = write(sk, buf, HCRP_PDU_HDR_SIZE);
160 	if (len < 0)
161 		return len;
162 
163 	len = read(sk, buf, sizeof(buf));
164 	if (len < 0)
165 		return len;
166 
167 	memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
168 	memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
169 
170 	if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
171 		errno = EIO;
172 		return -1;
173 	}
174 
175 	if (lpt_status)
176 		*lpt_status = rp.lpt_status;
177 
178 	return 0;
179 }
180 
hcrp_get_next_tid(int tid)181 static inline int hcrp_get_next_tid(int tid)
182 {
183 	if (tid > 0xf000)
184 		return 0;
185 	else
186 		return tid + 1;
187 }
188 
hcrp_print(bdaddr_t * src,bdaddr_t * dst,unsigned short ctrl_psm,unsigned short data_psm,int fd,int copies,const char * cups_class)189 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 {
191 	struct sockaddr_l2 addr;
192 	struct l2cap_options opts;
193 	socklen_t size;
194 	unsigned char buf[2048];
195 	int i, ctrl_sk, data_sk, count, len, timeout = 0;
196 	unsigned int mtu;
197 	uint8_t status;
198 	uint16_t tid = 0;
199 	uint32_t tmp, credit = 0;
200 
201 	if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
202 		perror("ERROR: Can't create socket");
203 		if (cups_class)
204 			return CUPS_BACKEND_FAILED;
205 		else
206 			return CUPS_BACKEND_RETRY;
207 	}
208 
209 	memset(&addr, 0, sizeof(addr));
210 	addr.l2_family = AF_BLUETOOTH;
211 	bacpy(&addr.l2_bdaddr, src);
212 
213 	if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
214 		perror("ERROR: Can't bind socket");
215 		close(ctrl_sk);
216 		if (cups_class)
217 			return CUPS_BACKEND_FAILED;
218 		else
219 			return CUPS_BACKEND_RETRY;
220 	}
221 
222 	memset(&addr, 0, sizeof(addr));
223 	addr.l2_family = AF_BLUETOOTH;
224 	bacpy(&addr.l2_bdaddr, dst);
225 	addr.l2_psm = htobs(ctrl_psm);
226 
227 	if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
228 		perror("ERROR: Can't connect to device");
229 		close(ctrl_sk);
230 		if (cups_class)
231 			return CUPS_BACKEND_FAILED;
232 		else
233 			return CUPS_BACKEND_RETRY;
234 	}
235 
236 	if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
237 		perror("ERROR: Can't create socket");
238 		close(ctrl_sk);
239 		if (cups_class)
240 			return CUPS_BACKEND_FAILED;
241 		else
242 			return CUPS_BACKEND_RETRY;
243 	}
244 
245 	memset(&addr, 0, sizeof(addr));
246 	addr.l2_family = AF_BLUETOOTH;
247 	bacpy(&addr.l2_bdaddr, src);
248 
249 	if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
250 		perror("ERROR: Can't bind socket");
251 		close(data_sk);
252 		close(ctrl_sk);
253 		if (cups_class)
254 			return CUPS_BACKEND_FAILED;
255 		else
256 			return CUPS_BACKEND_RETRY;
257 	}
258 
259 	memset(&addr, 0, sizeof(addr));
260 	addr.l2_family = AF_BLUETOOTH;
261 	bacpy(&addr.l2_bdaddr, dst);
262 	addr.l2_psm = htobs(data_psm);
263 
264 	if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
265 		perror("ERROR: Can't connect to device");
266 		close(data_sk);
267 		close(ctrl_sk);
268 		if (cups_class)
269 			return CUPS_BACKEND_FAILED;
270 		else
271 			return CUPS_BACKEND_RETRY;
272 	}
273 
274 	fputs("STATE: -connecting-to-device\n", stderr);
275 
276 	memset(&opts, 0, sizeof(opts));
277 	size = sizeof(opts);
278 
279 	if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
280 		perror("ERROR: Can't get socket options");
281 		close(data_sk);
282 		close(ctrl_sk);
283 		if (cups_class)
284 			return CUPS_BACKEND_FAILED;
285 		else
286 			return CUPS_BACKEND_RETRY;
287 	}
288 
289 	mtu = opts.omtu;
290 
291 	/* Ignore SIGTERM signals if printing from stdin */
292 	if (fd == 0) {
293 #ifdef HAVE_SIGSET
294 		sigset(SIGTERM, SIG_IGN);
295 #elif defined(HAVE_SIGACTION)
296 		memset(&action, 0, sizeof(action));
297 		sigemptyset(&action.sa_mask);
298 		action.sa_handler = SIG_IGN;
299 		sigaction(SIGTERM, &action, NULL);
300 #else
301 		signal(SIGTERM, SIG_IGN);
302 #endif /* HAVE_SIGSET */
303 	}
304 
305 	tid = hcrp_get_next_tid(tid);
306 	if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
307 		fprintf(stderr, "ERROR: Can't grant initial credits\n");
308 		close(data_sk);
309 		close(ctrl_sk);
310 		if (cups_class)
311 			return CUPS_BACKEND_FAILED;
312 		else
313 			return CUPS_BACKEND_RETRY;
314 	}
315 
316 	for (i = 0; i < copies; i++) {
317 
318 		if (fd != 0) {
319 			fprintf(stderr, "PAGE: 1 1\n");
320 			lseek(fd, 0, SEEK_SET);
321 		}
322 
323 		while (1) {
324 			if (credit < mtu) {
325 				tid = hcrp_get_next_tid(tid);
326 				if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
327 					credit += tmp;
328 					timeout = 0;
329 				}
330 			}
331 
332 			if (!credit) {
333 				if (timeout++ > 300) {
334 					tid = hcrp_get_next_tid(tid);
335 					if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
336 						fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
337 					break;
338 				}
339 
340 				sleep(1);
341 				continue;
342 			}
343 
344 			count = read(fd, buf, (credit > mtu) ? mtu : credit);
345 			if (count <= 0)
346 				break;
347 
348 			len = write(data_sk, buf, count);
349 			if (len < 0) {
350 				perror("ERROR: Error writing to device");
351 				close(data_sk);
352 				close(ctrl_sk);
353 				return CUPS_BACKEND_FAILED;
354 			}
355 
356 			if (len != count)
357 				fprintf(stderr, "ERROR: Can't send complete data\n");
358 
359 			credit -= len;
360 		}
361 
362 	}
363 
364 	close(data_sk);
365 	close(ctrl_sk);
366 
367 	return CUPS_BACKEND_OK;
368 }
369