Subversion Repositories heizung

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 andreas 1
/*
11 andreas 2
 * (C) Copyright 2011, 2024 by Andreas Theofilu <andreas@theosys.at>
5 andreas 3
 * All rights reserved!
4
 */
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <errno.h>
8
#include <string.h>
9
#include <ctype.h>
10
#include <unistd.h>
11
#include <sys/stat.h>
12
#include <fcntl.h>
13
#include <sys/select.h>
14
#include <sys/signal.h>
15
#include <time.h>
16
#include <syslog.h>
17
#include <termios.h>
18
#include "usb_comm.h"
19
 
20
#define INTR_TIMEOUT  3000
21
#define BULK_TIMEOUT  3000
22
 
23
#ifndef TRUE
24
   #define TRUE 1
25
#endif
26
 
27
#ifndef FALSE
28
   #define FALSE 0
29
#endif
30
 
31
/* something magic about 64, garmin driver will not return more than
32
 * 64 at a time. If you read less than 64 bytes the next read will
33
 * just get the last of the 64 byte buffer.
34
 */
35
#define ASYNC_DATA_SIZE 64
36
#define PRIV_PKTID_SET_MODE     2
37
#define PRIV_PKTID_INFO_RESP    4
38
#define PRIV_PKTID_INFO_REQ     3
39
 
40
#define SERIAL_USB_VID_PL2303  0x067b
41
#define SERIAL_USB_PID_PL2303  0x2303
42
 
43
#define SERIAL_DIR_NONE  0
44
#define SERIAL_DIR_READ  1
45
#define SERIAL_DIR_WRITE 2
46
 
47
const char *USBdevice = NULL;
48
struct termios ttyset, ttyset_old;
49
static fd_set all_fds;
50
void signal_handler_IO (int status);   /* definition of signal handler */
51
int wait_flag = TRUE;                    /* TRUE while no signal received */
52
SERDEV serialDev;
53
 
54
int serial_set_speed(SERDEV *ser, unsigned int speed, unsigned int stopbits);
55
 
56
void serial_set_device(const char *device)
57
{
58
	USBdevice = device;
59
}
60
 
61
void serial_set_method(int mth, unsigned int vid, unsigned int pid)
62
{
63
	serialDev.method = (mth != 0) ? 1 : 0;
64
 
65
	if (!serialDev.method && (!vid || !pid))
66
	   serialDev.method = 1;
67
 
68
	if (vid && pid)
69
	{
70
	   serialDev.USB_VID = vid;
71
	   serialDev.USB_PID = pid;
72
	}
73
}
74
 
75
/* Close the USB connection with the serial device. */
76
 
77
int serial_close()
78
{
79
int flag = 0;
80
 
81
	if (serialDev.method && serialDev.fd != -1)
82
	{
83
	   close(serialDev.fd);
84
	   serialDev.fd = -1;
85
	   serialDev.switch_fd = -1;
11 andreas 86
	   syslog(LOG_DAEMON | LOG_INFO,"Successful closed device %s", USBdevice);
5 andreas 87
	   USBdevice = NULL;
88
	   flag = 1;
89
	}
90
	else if (serialDev.handle != NULL )
91
	{
92
	   usb_release_interface(serialDev.handle,0);
93
	   usb_close(serialDev.handle);
94
	   serialDev.handle = NULL;
95
	   serialDev.switch_fd = -1;
11 andreas 96
	   syslog(LOG_DAEMON | LOG_INFO,"Successful closed device %u:%u", serialDev.USB_VID, serialDev.USB_PID);
5 andreas 97
	   flag = 1;
98
	}
99
 
100
	if (!flag)
11 andreas 101
	   syslog(LOG_DAEMON | LOG_ERR,"Error closing serial device for controlling heating!");
5 andreas 102
 
103
	return 0;
104
}
105
 
11 andreas 106
/*
5 andreas 107
   Open the USB connection with the first Garmin device we find.  Eventually,
108
   I'd like to add the ability to select a particular device.
109
*/
110
 
111
int serial_open()
112
{
113
struct usb_bus *     bi;
114
struct usb_device *  di;
115
int                  i;
116
static unsigned int rates[] = {0, 4800, 9600, 19200, 38400, 57600};
117
struct sigaction saio;
118
char hv0[1024];
119
 
120
	if (serialDev.method && serialDev.fd == -1)
121
	{
122
	   if ((serialDev.fd = open(USBdevice, O_RDWR | O_NDELAY)) == -1)
123
	   {
11 andreas 124
	      syslog(LOG_DAEMON | LOG_ERR, "Error opening device %s: %s", USBdevice, strerror(errno));
5 andreas 125
	      return 0;
126
	   }
127
 
128
	   serialDev.switch_fd = serialDev.fd;
11 andreas 129
	   syslog(LOG_DAEMON | LOG_INFO, "Successful opened device %s", USBdevice);
5 andreas 130
	   return 1;
131
	}
132
	else if (!serialDev.method && serialDev.handle == NULL)
133
	{
134
	   usb_init();
135
	   usb_find_busses();
136
	   usb_find_devices();
137
 
138
	   for (bi = usb_busses; bi != NULL; bi = bi->next )
139
	   {
140
	      for (di = bi->devices; di != NULL; di = di->next )
141
	      {
142
	         if (di->descriptor.idVendor  == serialDev.USB_VID &&
143
			di->descriptor.idProduct == serialDev.USB_PID)
144
		 {
11 andreas 145
		       syslog(LOG_DAEMON | LOG_INFO, "Found VID %04x, PID %04x on %s/%s!",
5 andreas 146
			di->descriptor.idVendor,
147
			di->descriptor.idProduct,
148
			bi->dirname,
149
			di->filename);
150
		 }
151
 
152
		 serialDev.handle = usb_open(di);
153
		 serialDev.read_bulk = 0;
154
 
155
		 if (serialDev.handle == NULL)
156
		 {
11 andreas 157
		    syslog(LOG_DAEMON | LOG_ERR, "usb_open failed: %s!",usb_strerror());
5 andreas 158
		    return 0;
159
		 }
160
 
161
		 if (usb_set_configuration(serialDev.handle, 1) < 0)
162
		 {
11 andreas 163
		    syslog(LOG_DAEMON | LOG_ERR, "usb_set_configuration failed: %s!",usb_strerror());
5 andreas 164
		    return 0;
165
		 }
166
 
167
		 if (usb_claim_interface(serialDev.handle,0) < 0)
168
		 {
11 andreas 169
		    syslog(LOG_DAEMON | LOG_ERR, "usb_claim_interface failed: %s!",usb_strerror());
5 andreas 170
		    return 0;
171
		 }
172
 
173
		 for (i = 0; i < di->config->interface->altsetting->bNumEndpoints; i++)
174
		 {
175
		 struct usb_endpoint_descriptor *ep;
176
 
177
		    ep = &di->config->interface->altsetting->endpoint[i];
178
 
179
		    switch (ep->bmAttributes & USB_ENDPOINT_TYPE_MASK )
180
		    {
181
			case USB_ENDPOINT_TYPE_BULK:
182
			     if ( ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK )
183
			        serialDev.bulk_in = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
184
			     else
185
			        serialDev.bulk_out = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
186
			break;
187
 
188
			case USB_ENDPOINT_TYPE_INTERRUPT:
189
			     if ( ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK )
190
			        serialDev.intr_in = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
191
			break;
192
 
193
			default:
194
			     break;
195
		       }
196
		 }
197
 
198
		 break;
199
	      }
200
 
201
	      if (serialDev.handle != NULL )
202
		 break;
203
	   }
204
 
205
	   if (serialDev.handle == NULL)
11 andreas 206
	      syslog(LOG_DAEMON | LOG_ERR, "Couldn't detect any serial device!");
5 andreas 207
	}
208
 
209
	return (serialDev.handle != NULL);
210
}
211
 
212
int serial_set_speed(SERDEV *ser, unsigned int speed, unsigned int stopbits)
213
{
214
unsigned int rate;
215
 
216
	if (!ser)
217
	   return 0;
218
 
219
	if (speed < 300)
220
	   rate = B0;
221
	else if (speed < 1200)
222
	   rate = B300;
223
	else if (speed < 2400)
224
	   rate = B1200;
225
	else if (speed < 4800)
226
	   rate = B2400;
227
	else if (speed < 9600)
228
	   rate = B4800;
229
	else if (speed < 19200)
230
	   rate = B9600;
231
	else if (speed < 38400)
232
	   rate = B19200;
233
	else if (speed < 57600)
234
	   rate = B38400;
235
	else if (speed < 115200)
236
	   rate = B57600;
237
	else
238
	   rate = B115200;
239
 
240
	tcflush(ser->fd, TCIOFLUSH); /* toss stale data */
241
 
242
	if (rate != cfgetispeed(&ttyset) || stopbits != 1)
243
	{
244
	   cfsetispeed(&ttyset, (speed_t)rate);
245
	   cfsetospeed(&ttyset, (speed_t)rate);
246
	   ttyset.c_cflag &=~ CSIZE;
247
	   ttyset.c_cflag |= (CSIZE & (stopbits == 2 ? CS7 : CS8));
248
 
249
	   if (tcsetattr(ser->fd, TCSANOW, &ttyset) != 0)
250
	      return 0;
251
 
252
	   tcflush(ser->fd, TCIOFLUSH);
253
	}
254
 
255
	return 1;
256
}