• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-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 <fcntl.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <termios.h>
35 
36 #include "csr.h"
37 
38 static uint16_t seqnum = 0x0000;
39 
40 static int fd = -1;
41 
csr_open_h4(char * device)42 int csr_open_h4(char *device)
43 {
44 	struct termios ti;
45 
46 	if (!device)
47 		device = "/dev/ttyS0";
48 
49 	fd = open(device, O_RDWR | O_NOCTTY);
50 	if (fd < 0) {
51 		fprintf(stderr, "Can't open serial port: %s (%d)\n",
52 						strerror(errno), errno);
53 		return -1;
54 	}
55 
56 	tcflush(fd, TCIOFLUSH);
57 
58 	if (tcgetattr(fd, &ti) < 0) {
59 		fprintf(stderr, "Can't get port settings: %s (%d)\n",
60 						strerror(errno), errno);
61 		close(fd);
62 		return -1;
63 	}
64 
65 	cfmakeraw(&ti);
66 
67 	ti.c_cflag |= CLOCAL;
68 	ti.c_cflag |= CRTSCTS;
69 
70 	cfsetospeed(&ti, B38400);
71 
72 	if (tcsetattr(fd, TCSANOW, &ti) < 0) {
73 		fprintf(stderr, "Can't change port settings: %s (%d)\n",
74 						strerror(errno), errno);
75 		close(fd);
76 		return -1;
77 	}
78 
79 	tcflush(fd, TCIOFLUSH);
80 
81 	return 0;
82 }
83 
do_command(uint16_t command,uint16_t seqnum,uint16_t varid,uint8_t * value,uint16_t length)84 static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
85 {
86 	unsigned char cp[254], rp[254];
87 	uint8_t cmd[10];
88 	uint16_t size;
89 	int len, offset = 3;
90 
91 	size = (length < 8) ? 9 : ((length + 1) / 2) + 5;
92 
93 	cmd[0] = command & 0xff;
94 	cmd[1] = command >> 8;
95 	cmd[2] = size & 0xff;
96 	cmd[3] = size >> 8;
97 	cmd[4] = seqnum & 0xff;
98 	cmd[5] = seqnum >> 8;
99 	cmd[6] = varid & 0xff;
100 	cmd[7] = varid >> 8;
101 	cmd[8] = 0x00;
102 	cmd[9] = 0x00;
103 
104 	memset(cp, 0, sizeof(cp));
105 	cp[0] = 0x01;
106 	cp[1] = 0x00;
107 	cp[2] = 0xfc;
108 	cp[3] = (size * 2) + 1;
109 	cp[4] = 0xc2;
110 	memcpy(cp + 5, cmd, sizeof(cmd));
111 	memcpy(cp + 15, value, length);
112 
113 	if (write(fd, cp, (size * 2) + 5) < 0)
114 		return -1;
115 
116 	switch (varid) {
117 	case CSR_VARID_COLD_RESET:
118 	case CSR_VARID_WARM_RESET:
119 	case CSR_VARID_COLD_HALT:
120 	case CSR_VARID_WARM_HALT:
121 		return 0;
122 	}
123 
124 	do {
125 		if (read(fd, rp, 1) < 1)
126 			return -1;
127 	} while (rp[0] != 0x04);
128 
129 	if (read(fd, rp + 1, 2) < 2)
130 		return -1;
131 
132 	do {
133 		len = read(fd, rp + offset, sizeof(rp) - offset);
134 		offset += len;
135 	} while (offset < rp[2] + 3);
136 
137 	if (rp[0] != 0x04 || rp[1] != 0xff || rp[3] != 0xc2) {
138 		errno = EIO;
139 		return -1;
140 	}
141 
142 	if ((rp[12] + (rp[13] << 8)) != 0) {
143 		errno = ENXIO;
144 		return -1;
145 	}
146 
147 	memcpy(value, rp + 14, length);
148 
149 	return 0;
150 }
151 
csr_read_h4(uint16_t varid,uint8_t * value,uint16_t length)152 int csr_read_h4(uint16_t varid, uint8_t *value, uint16_t length)
153 {
154 	return do_command(0x0000, seqnum++, varid, value, length);
155 }
156 
csr_write_h4(uint16_t varid,uint8_t * value,uint16_t length)157 int csr_write_h4(uint16_t varid, uint8_t *value, uint16_t length)
158 {
159 	return do_command(0x0002, seqnum++, varid, value, length);
160 }
161 
csr_close_h4(void)162 void csr_close_h4(void)
163 {
164 	close(fd);
165 }
166