Subversion Repositories public

Rev

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