Subversion Repositories public

Rev

Rev 142 | Rev 214 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
93 andreas 1
#include "config.h"
2
#include <stdio.h>
101 andreas 3
#include <stdlib.h>
4
#include <errno.h>
93 andreas 5
#include <string.h>
6
#include <ctype.h>
101 andreas 7
#include <unistd.h>
8
#include <sys/stat.h>
9
#include <fcntl.h>
10
#include <sys/select.h>
11
#include <sys/signal.h>
12
#include <time.h>
93 andreas 13
#include <usb.h>
14
#include "garmin.h"
15
 
101 andreas 16
/* #if defined (HAVE_SYS_TERMIOS_H)
17
   #include <sys/termios.h>
18
#else
19
   #if defined (HAVE_TERMIOS_H) */
20
      #include <termios.h>
21
/*   #endif
22
#endif
23
*/
93 andreas 24
#define INTR_TIMEOUT  3000
25
#define BULK_TIMEOUT  3000
26
 
101 andreas 27
#ifndef TRUE
28
   #define TRUE 1
29
#endif
93 andreas 30
 
101 andreas 31
#ifndef FALSE
32
   #define FALSE 0
33
#endif
34
 
35
/* something magic about 64, garmin driver will not return more than
36
 * 64 at a time. If you read less than 64 bytes the next read will
37
 * just get the last of the 64 byte buffer.
38
 */
39
#define ASYNC_DATA_SIZE 64
40
#define PRIV_PKTID_SET_MODE     2
41
#define PRIV_PKTID_INFO_RESP    4
42
#define PRIV_PKTID_INFO_REQ     3
43
#define GARMIN_LAYERID_PRIVATE  0x01106E4B
44
 
45
const char *USBdevice = NULL;
46
int method = 0;		/* 0 = Read directly from USB-Device, 1 = read from special device */
47
struct termios ttyset, ttyset_old;
48
static fd_set all_fds;
49
void signal_handler_IO (int status);   /* definition of signal handler */
50
int wait_flag = TRUE;                    /* TRUE while no signal received */
51
 
52
int garmin_set_speed(garmin_unit *garmin, unsigned int speed, unsigned int stopbits);
53
 
54
void garmin_set_device(const char *device)
55
{
56
	USBdevice = device;
57
}
58
 
59
void garmin_set_method(int mth)
60
{
61
	method = (mth != 0) ? 1 : 0;
62
}
63
 
93 andreas 64
/* Close the USB connection with the Garmin device. */
65
 
101 andreas 66
int garmin_close(garmin_unit *garmin)
93 andreas 67
{
101 andreas 68
	if (method && garmin->usb.fd != -1)
69
	{
70
	   if (isatty(garmin->usb.fd))
71
	   {
72
	      /* force hangup on close on systems that don't do HUPCL properly */
73
	      cfsetispeed(&ttyset, (speed_t)B0);
74
	      cfsetospeed(&ttyset, (speed_t)B0);
75
	      tcsetattr(garmin->usb.fd, TCSANOW, &ttyset);
76
	   }
93 andreas 77
 
101 andreas 78
	   /* this is the clean way to do it */
79
	   ttyset_old.c_cflag |= HUPCL;
80
	   tcsetattr(garmin->usb.fd, TCSANOW, &ttyset_old);
81
	   close(garmin->usb.fd);
82
	   garmin->usb.fd = -1;
83
	   USBdevice = NULL;
84
	}
85
	else if (garmin->usb.handle != NULL )
86
	{
87
	   usb_release_interface(garmin->usb.handle,0);
88
	   usb_close(garmin->usb.handle);
89
	   garmin->usb.handle = NULL;
90
	}
91
 
92
	return 0;
93 andreas 93
}
94
 
95
/* 
96
   Open the USB connection with the first Garmin device we find.  Eventually,
97
   I'd like to add the ability to select a particular device.
98
*/
99
 
101 andreas 100
int garmin_open(garmin_unit *garmin)
93 andreas 101
{
101 andreas 102
struct usb_bus *     bi;
103
struct usb_device *  di;
104
int                  i;
105
static unsigned int rates[] = {0, 4800, 9600, 19200, 38400, 57600};
106
garmin_packet p;
107
struct sigaction saio;
136 andreas 108
char hv0[1024];
93 andreas 109
 
101 andreas 110
	if (method && garmin->usb.fd == -1)
111
	{
112
	   /* check for USB serial drivers -- very Linux-specific */
150 andreas 113
/*	   if (access("/sys/module/garmin_gps", R_OK) != 0)
101 andreas 114
	   {
136 andreas 115
	      garmin_queue_error("garmin_gps not active!", err_error);
101 andreas 116
	      return 0;
117
	   }
150 andreas 118
*/
101 andreas 119
	   if ((garmin->usb.fd = open(USBdevice, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1)
120
	      return 0;
93 andreas 121
 
101 andreas 122
	   if (isatty(garmin->usb.fd))
123
	   {
124
	      /* install the signal handler before making the device asynchronous */
125
	      memset (&saio, 0, sizeof(struct sigaction));
126
	      saio.sa_handler = signal_handler_IO;
127
/*	      saio.sa_mask = 0;
128
	      saio.sa_flags = 0;
129
	      saio.sa_restorer = NULL; */
130
	      sigaction(SIGIO, &saio, NULL);
93 andreas 131
 
101 andreas 132
	      /* allow the process to receive SIGIO */
133
	      fcntl(garmin->usb.fd, F_SETOWN, getpid());
134
	      /* Make the file descriptor asynchronous (the manual page says only
135
		 O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
136
	      fcntl(garmin->usb.fd, F_SETFL, FASYNC);
137
	      tcgetattr(garmin->usb.fd, &ttyset_old);	/* save current port settings */
138
	      ttyset.c_cflag &= ~(PARENB | CRTSCTS);
139
	      ttyset.c_cflag |= CREAD | CLOCAL | B9600;
140
	      ttyset.c_iflag = ttyset.c_oflag = ttyset.c_lflag = (tcflag_t) 0;
141
	      ttyset.c_oflag = (ONLCR);
93 andreas 142
 
101 andreas 143
	      tcflush(garmin->usb.fd, TCIFLUSH);
144
	      tcsetattr(garmin->usb.fd, TCSANOW, &ttyset);
145
	   }
146
	   else
147
	   {
148
	      close(garmin->usb.fd);
149
	      garmin->usb.fd = -1;
150
	      return 0;
151
	   }
93 andreas 152
 
101 andreas 153
	   return 1;
154
	}
155
	else if (!method && garmin->usb.handle == NULL)
156
	{
157
	   usb_init();
158
	   usb_find_busses();
159
	   usb_find_devices();
160
 
161
	   for ( bi = usb_busses; bi != NULL; bi = bi->next )
162
	   {
163
	      for ( di = bi->devices; di != NULL; di = di->next )
164
	      {
165
	         if ( di->descriptor.idVendor  == GARMIN_USB_VID &&
166
			di->descriptor.idProduct == GARMIN_USB_PID )
167
		 {
168
 
169
		    if ( garmin->verbose != 0 )
170
		    {
136 andreas 171
		       sprintf(hv0, "[garmin] found VID %04x, PID %04x on %s/%s!",
101 andreas 172
			di->descriptor.idVendor,
173
			di->descriptor.idProduct,
174
			bi->dirname,
175
			di->filename);
136 andreas 176
		       garmin_queue_error(hv0, err_info);
101 andreas 177
		    }
178
 
179
		    garmin->usb.handle = usb_open(di);
180
		    garmin->usb.read_bulk = 0;
181
 
182
		    if ( garmin->usb.handle == NULL )
183
		    {
136 andreas 184
		       sprintf(hv0, "usb_open failed: %s!",usb_strerror());
185
		       garmin_queue_error(hv0, err_error);
101 andreas 186
		       return 0;
187
		    }
188
 
136 andreas 189
		    if (usb_set_configuration(garmin->usb.handle, 1) < 0 )
101 andreas 190
		    {
136 andreas 191
		       sprintf(hv0, "usb_set_configuration failed: %s!",usb_strerror());
192
		       garmin_queue_error(hv0, err_error);
101 andreas 193
		       return 0;
194
		    }
195
 
196
		    if ( usb_claim_interface(garmin->usb.handle,0) < 0 )
197
		    {
136 andreas 198
		       sprintf(hv0, "usb_claim_interface failed: %s!",usb_strerror());
199
		       garmin_queue_error(hv0, err_error);
101 andreas 200
		       return 0;
201
		    }
202
 
203
		    for ( i = 0; i < di->config->interface->altsetting->bNumEndpoints; i++ )
204
		    {
205
		     struct usb_endpoint_descriptor * ep;
206
 
207
		       ep = &di->config->interface->altsetting->endpoint[i];
208
 
209
		       switch ( ep->bmAttributes & USB_ENDPOINT_TYPE_MASK )
210
		       {
211
			  case USB_ENDPOINT_TYPE_BULK:
212
			     if ( ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK )
213
			     {
214
			        garmin->usb.bulk_in = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
215
			     }
216
			     else
217
			     {
218
			        garmin->usb.bulk_out = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
219
			     }
220
			  break;
221
 
222
			  case USB_ENDPOINT_TYPE_INTERRUPT:
223
			     if ( ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK )
224
			     {
225
			        garmin->usb.intr_in = ep->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
226
			     }
227
			  break;
228
 
229
			  default:
230
			     break;
231
		       }
232
		    }
233
 
234
		    break;
235
	         }
93 andreas 236
	      }
237
 
101 andreas 238
	      if ( garmin->usb.handle != NULL )
239
		 break;
240
	   }
136 andreas 241
 
142 andreas 242
	   if (garmin->usb.handle == NULL)
243
	      garmin_queue_error("Couldn't detect any Garmin device!", err_info);
93 andreas 244
	}
245
 
101 andreas 246
	return (garmin->usb.handle != NULL);
93 andreas 247
}
248
 
101 andreas 249
void signal_handler_IO (int status)
250
{
251
	wait_flag = FALSE;
252
}
93 andreas 253
 
101 andreas 254
int garmin_set_speed(garmin_unit *garmin, unsigned int speed, unsigned int stopbits)
93 andreas 255
{
101 andreas 256
unsigned int rate;
257
 
258
	if (speed < 300)
259
	   rate = B0;
260
	else if (speed < 1200)
261
	   rate = B300;
262
	else if (speed < 2400)
263
	   rate = B1200;
264
	else if (speed < 4800)
265
	   rate = B2400;
266
	else if (speed < 9600)
267
	   rate = B4800;
268
	else if (speed < 19200)
269
	   rate = B9600;
270
	else if (speed < 38400)
271
	   rate = B19200;
272
	else if (speed < 57600)
273
	   rate = B38400;
274
	else if (speed < 115200)
275
	   rate = B57600;
276
	else
277
	   rate = B115200;
278
 
279
	tcflush(garmin->usb.fd, TCIOFLUSH); /* toss stale data */
280
 
281
	if (rate != cfgetispeed(&ttyset) || stopbits != 1)
282
	{
283
	   cfsetispeed(&ttyset, (speed_t)rate);
284
	   cfsetospeed(&ttyset, (speed_t)rate);
285
	   ttyset.c_cflag &=~ CSIZE;
286
	   ttyset.c_cflag |= (CSIZE & (stopbits == 2 ? CS7 : CS8));
287
 
288
	   if (tcsetattr(garmin->usb.fd, TCSANOW, &ttyset) != 0)
289
	      return 0;
290
 
291
	   tcflush(garmin->usb.fd, TCIOFLUSH);
292
	}
293
 
294
/*	if ((session->packet_type = packet_sniff(session)) == BAD_PACKET)
295
	   return 0;
296
*/
297
	return 1;
93 andreas 298
}
299
 
101 andreas 300
uint8 garmin_packet_type(garmin_packet *p)
301
{
302
	return p->packet.type;
303
}
93 andreas 304
 
101 andreas 305
 
306
uint16 garmin_packet_id(garmin_packet *p)
93 andreas 307
{
101 andreas 308
	return get_uint16(p->packet.id);
93 andreas 309
}
310
 
311
 
101 andreas 312
uint32 garmin_packet_size(garmin_packet *p)
93 andreas 313
{
101 andreas 314
	return get_uint32(p->packet.size);
93 andreas 315
}
316
 
317
 
101 andreas 318
uint8 *garmin_packet_data(garmin_packet *p)
93 andreas 319
{
101 andreas 320
	return p->packet.data;
93 andreas 321
}
322
 
323
 
101 andreas 324
int garmin_packetize(garmin_packet *p, uint16 id, uint32 size, uint8 *data)
93 andreas 325
{
101 andreas 326
int ok = 0;
93 andreas 327
 
101 andreas 328
	if (size + PACKET_HEADER_SIZE < sizeof(garmin_packet))
329
	{
330
	   p->packet.type       = GARMIN_PROTOCOL_APP;
331
	   p->packet.reserved1  = 0;
332
	   p->packet.reserved2  = 0;
333
	   p->packet.reserved3  = 0;
334
	   p->packet.id[0]      = id;
335
	   p->packet.id[1]      = id >> 8;
336
	   p->packet.reserved4  = 0;
337
	   p->packet.reserved5  = 0;
338
	   p->packet.size[0]    = size;
339
	   p->packet.size[1]    = size >> 8;
340
	   p->packet.size[2]    = size >> 16;
341
	   p->packet.size[3]    = size >> 24;
93 andreas 342
 
101 andreas 343
	   if ( size > 0 && data != NULL )
344
	   {
345
	      memcpy(p->packet.data,data,size);
346
	   }
347
 
348
	   ok = 1;
349
	}
350
 
351
	return ok;
93 andreas 352
}
353
 
354
 
101 andreas 355
int garmin_read(garmin_unit *garmin, garmin_packet *p)
93 andreas 356
{
101 andreas 357
int r = -1;
358
int cnt = 0;
359
int bLen = 0;
360
struct timespec delay, rem;
361
fd_set fds, rfds;
362
struct timeval tv;
363
int sel_ret = 0;
364
int ok = 0;
136 andreas 365
char hv0[1024];
93 andreas 366
 
101 andreas 367
	if (garmin->usb.fd == -1 && garmin->usb.handle == NULL)
368
	   garmin_open(garmin);
93 andreas 369
 
101 andreas 370
	if (method && garmin->usb.fd != -1)
371
	{
372
	   long theBytesReturned = 0;
373
	   char *buf = (char *)p->data;
374
 
375
	   for(cnt = 0 ; cnt < 10 ; cnt++)
376
	   {
377
	      if (wait_flag != FALSE)
378
	      {
379
		 cnt--;
380
		 usleep (100000);
381
		 continue;
382
	      }
383
 
384
	      /* Read async data until the driver returns less than the
385
	       * max async data size, which signifies the end of a packet
386
	       * not optimal, but given the speed and packet nature of
387
	       * the USB not too bad for a start
388
	       */
389
	      wait_flag = TRUE;
390
 
391
	      theBytesReturned = read(garmin->usb.fd, buf + bLen, ASYNC_DATA_SIZE);
392
 
393
	      if (0 > theBytesReturned)
394
	      {
395
		 /* read error...
396
		  * or EAGAIN, but O_NONBLOCK is never set
397
		  */
136 andreas 398
		 sprintf(hv0, "Read error=%ld, errno=%d!", theBytesReturned, errno);
399
		 garmin_queue_error(hv0, err_error);
101 andreas 400
		 continue;
401
	      }
402
 
136 andreas 403
	      sprintf(hv0, "got %ld bytes.", theBytesReturned);
404
	      garmin_queue_error(hv0, err_info);
101 andreas 405
	      bLen += theBytesReturned;
406
 
407
	      if (theBytesReturned < ASYNC_DATA_SIZE)
408
	      {
409
		 /* zero length, or short, read is a flag for got the whole packet */
410
		 break;
411
	      }
412
 
413
	      if (256 <= bLen)
414
	      {
415
		 /* really bad read error... */
416
		 bLen = 0;
136 andreas 417
		 garmin_queue_error("Packet too long!", err_fatal);
101 andreas 418
		 break;
419
	      }
420
 
421
	      delay.tv_sec = 0;
422
	      delay.tv_nsec = 3330000L;
423
 
424
	      while (nanosleep(&delay, &rem) < 0)
425
	         continue;
426
	   }
427
	}
428
	else if (garmin->usb.handle != NULL)
429
	{
430
	   if (garmin->usb.read_bulk == 0)
431
	   {
432
	      r = usb_interrupt_read(garmin->usb.handle,
93 andreas 433
			     garmin->usb.intr_in,
434
			     p->data,
435
			     sizeof(garmin_packet),
436
			     INTR_TIMEOUT);
101 andreas 437
	      /* 
438
	       * If the packet is a "Pid_Data_Available" packet, we need to read
439
	       * from the bulk endpoint until we get an empty packet.
440
	       */
441
 
442
	      if (garmin_packet_type(p) == GARMIN_PROTOCOL_USB &&
443
			garmin_packet_id(p) == Pid_Data_Available)
444
	      {
445
		 /* FIXME!!! */
136 andreas 446
		 sprintf(hv0, "Received a Pid_Data_Available from the unit!");
447
		 garmin_queue_error(hv0, err_warning);
101 andreas 448
	      }
449
	   }
450
	   else
451
	   {
452
	      r = usb_bulk_read(garmin->usb.handle,
93 andreas 453
			garmin->usb.bulk_in,
454
			p->data,
455
			sizeof(garmin_packet),
456
			BULK_TIMEOUT);
101 andreas 457
	   }
458
	}
93 andreas 459
 
101 andreas 460
	if (garmin->verbose != 0 && r >= 0)
461
	{
462
	   garmin_print_packet(p, GARMIN_DIR_READ, stdout);
463
	}
93 andreas 464
 
101 andreas 465
	return r;
93 andreas 466
}
467
 
468
 
101 andreas 469
int garmin_write(garmin_unit *garmin, garmin_packet *p)
93 andreas 470
{
101 andreas 471
int r = -1;
472
int s = garmin_packet_size(p) + PACKET_HEADER_SIZE;
93 andreas 473
 
101 andreas 474
	if (garmin->usb.fd == -1 && garmin->usb.handle == NULL)
475
	   garmin_open(garmin);
93 andreas 476
 
101 andreas 477
	if (garmin->usb.handle != NULL || garmin->usb.fd != -1)
478
	{
479
	   if (garmin->verbose != 0)
480
	   {
481
	      garmin_print_packet(p, GARMIN_DIR_WRITE, stdout);
482
	   }
93 andreas 483
 
101 andreas 484
	   if (method)
485
	      r = write(garmin->usb.fd, p->data, s);
486
	   else
487
	      r = usb_bulk_write(garmin->usb.handle,
93 andreas 488
		       garmin->usb.bulk_out,
489
		       p->data,
490
		       s,
491
		       BULK_TIMEOUT);
101 andreas 492
 
493
	   if (r != s)
494
	   {
136 andreas 495
	   char hv0[1024];
496
 
101 andreas 497
	      if (method)
136 andreas 498
	      {
499
		 sprintf(hv0, "Write to device failed!");
500
		 garmin_queue_error(hv0, err_error);
501
	      }
101 andreas 502
	      else
136 andreas 503
	      {
504
		 sprintf(stderr, "usb_bulk_write failed: %s!", usb_strerror());
505
		 garmin_queue_error(hv0, err_error);
506
	      }
101 andreas 507
 
508
	      return 0;
509
	   }
510
	}
511
 
512
	return r;
93 andreas 513
}
514
 
515
 
101 andreas 516
uint32 garmin_start_session(garmin_unit *garmin)
93 andreas 517
{
101 andreas 518
garmin_packet p;
519
int i;
520
fd_set fds, rfds;
521
struct timeval tv;
522
int sel_ret = 0;
523
int ok = 0;
93 andreas 524
 
101 andreas 525
	garmin_packetize(&p, Pid_Start_Session, 0, NULL);
526
	p.packet.type = GARMIN_PROTOCOL_USB;
93 andreas 527
 
101 andreas 528
	if (method && garmin->usb.fd != -1)
529
	{
530
	   FD_ZERO(&fds);
531
	   FD_SET(garmin->usb.fd, &fds);
532
	}
93 andreas 533
 
101 andreas 534
	garmin_write(garmin, &p);
535
	garmin_write(garmin, &p);
536
	garmin_write(garmin, &p);
537
 
538
	if (garmin_read(garmin, &p) == 16)
539
	{
540
	   garmin->id = get_uint32(p.packet.data);
541
	}
542
	else
543
	{
544
	   garmin->id = 0;
545
	}
546
 
136 andreas 547
	garmin_callback("start_session");
101 andreas 548
	return garmin->id;
93 andreas 549
}
550
 
551
 
101 andreas 552
void garmin_print_packet(garmin_packet *p, int dir, FILE *fp)
93 andreas 553
{
101 andreas 554
int    i;
555
int    j;
556
uint32 s;
557
char   hex[128];
558
char   dec[128];
93 andreas 559
 
101 andreas 560
	s = garmin_packet_size(p);
93 andreas 561
 
101 andreas 562
	switch ( dir )
563
	{
564
	   case GARMIN_DIR_READ:   fprintf(fp,"<read");   break;
565
	   case GARMIN_DIR_WRITE:  fprintf(fp,"<write");  break;
566
	   default:                fprintf(fp,"<packet");        break;
567
	}
93 andreas 568
 
101 andreas 569
	fprintf(fp," type=\"0x%02x\" id=\"0x%04x\" size=\"%u\"",
93 andreas 570
	  garmin_packet_type(p),garmin_packet_id(p),s);
101 andreas 571
 
572
	if (s > 0)
573
	{
574
	   fprintf(fp,">\n");
575
 
576
	   for ( i = 0, j = 0; i < s; i++ )
577
	   {
578
	      sprintf(&hex[(3*(i&0x0f))]," %02x",p->packet.data[i]);
579
	      sprintf(&dec[(i&0x0f)],"%c",
580
		(isalnum(p->packet.data[i]) ||
581
		ispunct(p->packet.data[i]) ||
582
		p->packet.data[i] == ' ') ?
583
		p->packet.data[i] : '_');
584
 
585
	      if ( (i & 0x0f) == 0x0f )
586
	      {
587
		 j = 0;
588
		 fprintf(fp,"[%04x] %-54s %s\n",i-15,hex,dec);
589
	      }
590
	      else
591
	      {
592
		 j++;
593
	      }
594
	   }
595
 
596
	   if (j > 0)
597
	   {
598
	      fprintf(fp,"[%04x] %-54s %s\n",s-(s & 0x0f),hex,dec);
599
	   }
600
 
601
	   switch (dir)
602
	   {
603
	      case GARMIN_DIR_READ:   fprintf(fp,"</read>\n");   break;
604
	      case GARMIN_DIR_WRITE:  fprintf(fp,"</write>\n");  break;
605
	      default:                fprintf(fp,"</packet>\n"); break;
606
	   }
607
	}
608
	else
609
	{
610
	   fprintf(fp,"/>\n");
611
	}
93 andreas 612
}