Subversion Repositories public

Rev

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