Home | History | Annotate | Download | only in tools
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) 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 #include "ubcsp.h"
     38 
     39 static uint16_t seqnum = 0x0000;
     40 
     41 static int fd = -1;
     42 
     43 static struct ubcsp_packet send_packet;
     44 static uint8_t send_buffer[512];
     45 
     46 static struct ubcsp_packet receive_packet;
     47 static uint8_t receive_buffer[512];
     48 
     49 int csr_open_bcsp(char *device, speed_t bcsp_rate)
     50 {
     51 	struct termios ti;
     52 	uint8_t delay, activity = 0x00;
     53 	int timeout = 0;
     54 
     55 	if (!device)
     56 		device = "/dev/ttyS0";
     57 
     58 	fd = open(device, O_RDWR | O_NOCTTY);
     59 	if (fd < 0) {
     60 		fprintf(stderr, "Can't open serial port: %s (%d)\n",
     61 						strerror(errno), errno);
     62 		return -1;
     63 	}
     64 
     65 	tcflush(fd, TCIOFLUSH);
     66 
     67 	if (tcgetattr(fd, &ti) < 0) {
     68 		fprintf(stderr, "Can't get port settings: %s (%d)\n",
     69 						strerror(errno), errno);
     70 		close(fd);
     71 		return -1;
     72 	}
     73 
     74 	cfmakeraw(&ti);
     75 
     76 	ti.c_cflag |=  CLOCAL;
     77 	ti.c_cflag &= ~CRTSCTS;
     78 	ti.c_cflag |=  PARENB;
     79 	ti.c_cflag &= ~PARODD;
     80 	ti.c_cflag &= ~CSIZE;
     81 	ti.c_cflag |=  CS8;
     82 	ti.c_cflag &= ~CSTOPB;
     83 
     84 	ti.c_cc[VMIN] = 1;
     85 	ti.c_cc[VTIME] = 0;
     86 
     87 	cfsetospeed(&ti, bcsp_rate);
     88 
     89 	if (tcsetattr(fd, TCSANOW, &ti) < 0) {
     90 		fprintf(stderr, "Can't change port settings: %s (%d)\n",
     91 						strerror(errno), errno);
     92 		close(fd);
     93 		return -1;
     94 	}
     95 
     96 	tcflush(fd, TCIOFLUSH);
     97 
     98 	if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) {
     99 		fprintf(stderr, "Can't set non blocking mode: %s (%d)\n",
    100 						strerror(errno), errno);
    101 		close(fd);
    102 		return -1;
    103 	}
    104 
    105 	memset(&send_packet, 0, sizeof(send_packet));
    106 	memset(&receive_packet, 0, sizeof(receive_packet));
    107 
    108 	ubcsp_initialize();
    109 
    110 	send_packet.length = 512;
    111 	send_packet.payload = send_buffer;
    112 
    113 	receive_packet.length = 512;
    114 	receive_packet.payload = receive_buffer;
    115 
    116 	ubcsp_receive_packet(&receive_packet);
    117 
    118 	while (1) {
    119 		delay = ubcsp_poll(&activity);
    120 
    121 		if (activity & UBCSP_PACKET_RECEIVED)
    122 			break;
    123 
    124 		if (delay) {
    125 			usleep(delay * 100);
    126 
    127 			if (timeout++ > 5000) {
    128 				fprintf(stderr, "Initialization timed out\n");
    129 				return -1;
    130 			}
    131 		}
    132 	}
    133 
    134 	return 0;
    135 }
    136 
    137 void put_uart(uint8_t ch)
    138 {
    139 	if (write(fd, &ch, 1) < 0)
    140 		fprintf(stderr, "UART write error\n");
    141 }
    142 
    143 uint8_t get_uart(uint8_t *ch)
    144 {
    145 	int res = read(fd, ch, 1);
    146 	return res > 0 ? res : 0;
    147 }
    148 
    149 static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
    150 {
    151 	unsigned char cp[254], rp[254];
    152 	uint8_t cmd[10];
    153 	uint16_t size;
    154 	uint8_t delay, activity = 0x00;
    155 	int timeout = 0, sent = 0;
    156 
    157 	size = (length < 8) ? 9 : ((length + 1) / 2) + 5;
    158 
    159 	cmd[0] = command & 0xff;
    160 	cmd[1] = command >> 8;
    161 	cmd[2] = size & 0xff;
    162 	cmd[3] = size >> 8;
    163 	cmd[4] = seqnum & 0xff;
    164 	cmd[5] = seqnum >> 8;
    165 	cmd[6] = varid & 0xff;
    166 	cmd[7] = varid >> 8;
    167 	cmd[8] = 0x00;
    168 	cmd[9] = 0x00;
    169 
    170 	memset(cp, 0, sizeof(cp));
    171 	cp[0] = 0x00;
    172 	cp[1] = 0xfc;
    173 	cp[2] = (size * 2) + 1;
    174 	cp[3] = 0xc2;
    175 	memcpy(cp + 4, cmd, sizeof(cmd));
    176 	memcpy(cp + 14, value, length);
    177 
    178 	receive_packet.length = 512;
    179 	ubcsp_receive_packet(&receive_packet);
    180 
    181 	send_packet.channel  = 5;
    182 	send_packet.reliable = 1;
    183 	send_packet.length   = (size * 2) + 4;
    184 	memcpy(send_packet.payload, cp, (size * 2) + 4);
    185 
    186 	ubcsp_send_packet(&send_packet);
    187 
    188 	while (1) {
    189 		delay = ubcsp_poll(&activity);
    190 
    191 		if (activity & UBCSP_PACKET_SENT) {
    192 			switch (varid) {
    193 			case CSR_VARID_COLD_RESET:
    194 			case CSR_VARID_WARM_RESET:
    195 			case CSR_VARID_COLD_HALT:
    196 			case CSR_VARID_WARM_HALT:
    197 				return 0;
    198 			}
    199 
    200 			sent = 1;
    201 			timeout = 0;
    202 		}
    203 
    204 		if (activity & UBCSP_PACKET_RECEIVED) {
    205 			if (sent && receive_packet.channel == 5 &&
    206 					receive_packet.payload[0] == 0xff) {
    207 				memcpy(rp, receive_packet.payload,
    208 							receive_packet.length);
    209 				break;
    210 			}
    211 
    212 			receive_packet.length = 512;
    213 			ubcsp_receive_packet(&receive_packet);
    214 			timeout = 0;
    215 		}
    216 
    217 		if (delay) {
    218 			usleep(delay * 100);
    219 
    220 			if (timeout++ > 5000) {
    221 				fprintf(stderr, "Operation timed out\n");
    222 				return -1;
    223 			}
    224 		}
    225 	}
    226 
    227 	if (rp[0] != 0xff || rp[2] != 0xc2) {
    228 		errno = EIO;
    229 		return -1;
    230 	}
    231 
    232 	if ((rp[11] + (rp[12] << 8)) != 0) {
    233 		errno = ENXIO;
    234 		return -1;
    235 	}
    236 
    237 	memcpy(value, rp + 13, length);
    238 
    239 	return 0;
    240 }
    241 
    242 int csr_read_bcsp(uint16_t varid, uint8_t *value, uint16_t length)
    243 {
    244 	return do_command(0x0000, seqnum++, varid, value, length);
    245 }
    246 
    247 int csr_write_bcsp(uint16_t varid, uint8_t *value, uint16_t length)
    248 {
    249 	return do_command(0x0002, seqnum++, varid, value, length);
    250 }
    251 
    252 void csr_close_bcsp(void)
    253 {
    254 	close(fd);
    255 }
    256