hcrp.c 7.6 KB

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