static void psp_write(void) { short int s; unsigned char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* the header: */ /* 31 6E 69 50 20 00 00 00 08 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ /* offset 0x0C - 0x0D = 2 byte pin count */ s = waypt_count(); if (global_opts.synthesize_shortnames) { setshort_length(mkshort_handle, 32); setshort_whitespace_ok(mkshort_handle, 1); } if (s > MAXPSPOUTPUTPINS) { fatal(MYNAME ": attempt to output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS); } /* insert waypoint count into header */ le_write16(&header_bytes[12], s); gbfwrite(header_bytes, 1, 32, psp_file_out); waypt_disp_all(psp_waypt_pr); }
void gusb_syncup(void) { static int unit_number; static const char oinit[12] = {0, 0, 0, 0, GUSB_SESSION_START, 0, 0, 0, 0, 0, 0, 0}; garmin_usb_packet iresp; int i; /* * This is our first communication with the unit. */ receive_state = rs_fromintr; for(i = 0; i < 25; i++) { le_write16(&iresp.gusb_pkt.pkt_id, 0); le_write32(&iresp.gusb_pkt.datasz, 0); le_write32(&iresp.gusb_pkt.databuf, 0); gusb_cmd_send((const garmin_usb_packet *) oinit, sizeof(oinit)); gusb_cmd_get(&iresp, sizeof(iresp)); if ((le_read16(iresp.gusb_pkt.pkt_id) == GUSB_SESSION_ACK) && (le_read32(iresp.gusb_pkt.datasz) == 4)) { unsigned serial_number = le_read32(iresp.gusb_pkt.databuf); garmin_unit_info[unit_number].serial_number = serial_number; gusb_id_unit(&garmin_unit_info[unit_number]); unit_number++; return; } } fatal("Unable to establish USB syncup\n"); }
void CPocketStreetPushPinsWriter::Open(const TCHAR* pFilename) { CGPSWriter::Open(pFilename); unsigned char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* the header: */ /* 31 6E 69 50 20 00 00 00 08 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 */ /* offset 0x0C - 0x0D = 2 byte pin count */ /* insert waypoint count into header */ le_write16(&header_bytes[12], m_TotalPushPins); fwrite(header_bytes, 1, 32, m_fd); }
int32 GPS_Write_Packet_usb(gpsdevh *dh, GPS_PPacket packet) { garmin_usb_packet gp; memset(&gp, 0, sizeof(gp)); /* * Take the "portable" GPS_Packet data and put them into * the USB packet that we will put on the wire. */ gp.gusb_pkt.type = 0x14; le_write16(&gp.gusb_pkt.pkt_id, packet->type); le_write32(&gp.gusb_pkt.datasz, packet->n ); memcpy(&gp.gusb_pkt.databuf, packet->data, packet->n); return gusb_cmd_send(&gp, packet->n + 12); }
/* * This was a function of great joy to discover...and even greater to maintain. * * It turns out that as of 5/2006, every Garmin USB product has a problem * where the device does not reset the data toggles after a configuration * set. After a reset, the toggles both match. So we tear through the * conversation and life is good. Unfortunately, the second time through, * if we had an odd number of transactions in the previous conversation, * we send a configuration set and reset the toggle on the HCI but the * toggle on the device's end of the pipe is now out of whack which means * that the subsequent transaction will hang. * * This isn't a problem in Windows since the configuration set is done only * once there. * * This code has been tested in loops of 1000 cycles on Linux and OS/X and * it seems to cure this at a mere cost of complexity and startup time. I'll * be delighted when all the firmware gets revved and updated and we can * remove this. * * 9/2008 But wait, there's more. The very toggle reset that we *had* to * implement in 2006 to make non-Windows OSes work actually locks up verion * 2.70 of the Venture HC. On that model, the second product request * (you know, the one that we *use*, locks that device's protocol stack * after the RET2INTR that immediately follows the REQBLK (and why is it * telling us to go into bulk mode followed by an immeidate EOF, anyway?) * that follows the request for product ID. 100% reproducible on Mac and * Linux. Of course, we don't see this on the Windows system becuase * we don't have to jump through hooops to clear the spec-violating out * of state toggles there becuase those systems see only one configuration * set ever. * * Grrrr! */ unsigned gusb_reset_toggles(void) { static const char oinit[12] = {0, 0, 0, 0, GUSB_SESSION_START, 0, 0, 0, 0, 0, 0, 0}; static const char oid[12] = {20, 0, 0, 0, 0xfe, 0, 0, 0, 0, 0, 0, 0}; garmin_usb_packet iresp; int t; unsigned rv = 0; /* Start off with three session starts. * #1 resets the bulk out toggle. It may not make it to the device. * #2 resets the the intr in toggle. It will make it to the device * since #1 reset the the bulk out toggle. The device will * respond on the intr in pipe which will clear its toggle. * #3 actually starts the session now that the above are both clear. */ gusb_cmd_send((const garmin_usb_packet *) oinit, sizeof(oinit)); gusb_cmd_send((const garmin_usb_packet *) oinit, sizeof(oinit)); gusb_cmd_send((const garmin_usb_packet *) oinit, sizeof(oinit)); t = 10; while(1) { le_write16(&iresp.gusb_pkt.pkt_id, 0); le_write32(&iresp.gusb_pkt.datasz, 0); le_write32(&iresp.gusb_pkt.databuf, 0); gusb_cmd_get(&iresp, sizeof(iresp)); if ((le_read16(iresp.gusb_pkt.pkt_id) == GUSB_SESSION_ACK) && (le_read32(iresp.gusb_pkt.datasz) == 4)) { break; } if (t-- <= 0) { fatal("Could not start session in a reasonable number of tries.\n"); } } /* * Now that the bulk out and intr in packets are good, we send * a product ID. On devices that respond totally on the intr * pipe, this does nothing interesting, but on devices that respon * on the bulk pipe this will reset the toggles on the bulk in. */ t = 10; gusb_cmd_send((const garmin_usb_packet *) oid, sizeof(oid)); while(1) { le_write16(&iresp.gusb_pkt.pkt_id, 0); le_write32(&iresp.gusb_pkt.datasz, 0); le_write32(&iresp.gusb_pkt.databuf, 0); gusb_cmd_get(&iresp, sizeof(iresp)); if (le_read16(iresp.gusb_pkt.pkt_id) == 0xff) { rv = le_read16(iresp.gusb_pkt.databuf+0); } if (le_read16(iresp.gusb_pkt.pkt_id) == 0xfd) return rv; if (t-- <= 0) { fatal("Could not start session in a reasonable number of tries.\n"); } } return 0; }
// Called for each cache to write out the corresponding waypoint to be used by the GPS void CPocketStreetPushPinsWriter::OnCache(CGeoCache& Cache) { #ifndef M_PI #define M_PI 3.14159265358979323846 #endif AW_CONVERSION; char tbuf[64]; int i; /* convert lat/long back to radians */ double lat = (Cache.m_Lat * M_PI) / 180.0; double lon = (Cache.m_Long * M_PI) / 180.0; m_PIndex++; le_write16(tbuf, m_PIndex); /* 2 bytes - pin index */ fwrite(tbuf, 1, 2, m_fd); /* 2 bytes - null bytes */ memset(tbuf, '\0', sizeof(tbuf)); fwrite(tbuf, 1, 2, m_fd); /* set the grid byte */ char c = grid_byte(Cache.m_Lat, Cache.m_Long); /* since the grid byte matches with what pocketstreets does to */ /* input files, our output appears identical to a pin file that */ /* has already been processed and corrected by pocketstreets. */ /* Due to the grid and signs, it'll look different than one that */ /* comes straight from S&T. */ /* the grid byte */ fwrite(&c, 1, 1, m_fd); /* 8 bytes - latitude/radians */ psp_fwrite_double(lat, m_fd); /* 8 bytes - longitude/radians */ psp_fwrite_double(lon, m_fd); /* 1 byte - pin properties */ c = 0x14; /* display pin name on, display notes on. 0x04 = no notes */ fwrite(&c, 1, 1, m_fd); memset(tbuf, '\0', sizeof(tbuf)); /* 3 unknown bytes */ fwrite(tbuf, 1, 3, m_fd); char Icon[2] = {0,0}; /* Traditional is a red box with a flag Mystery Cache is the pushpin. Multi is the Flags Event is the bubble text icon. Virtual is the arrow pointing right. */ #define IconPin 0 #define IconBubble 1 #define IconRedBoxFlag 4 #define IconArrowToLeft 8 #define IconArrowToRight 9 #define IconArrowDown 10 #define IconFlags 18 #define IconLetter 29 switch (Cache.TypeLookup()) { case GT_Traditional: Icon[0] = IconRedBoxFlag; break; case GT_Multi: Icon[0] = IconFlags; break; case GT_Virtual: Icon[0] = IconArrowToRight; break; case GT_Webcam: Icon[0] = IconArrowDown; break; case GT_Unknown: Icon[0] = IconPin; break; case GT_LetterboxHybrid: Icon[0] = IconLetter; break; case GT_Event: Icon[0] = IconBubble; break; case GT_ProjectAPE: Icon[0] = IconRedBoxFlag; break; case GT_Locationless: Icon[0] = IconArrowToLeft; break; case GT_CITO: Icon[0] = IconBubble; break; case GT_Earthcache: Icon[0] = IconArrowToRight; break; } /* 1 icon byte 0x00 = PIN */ fwrite(&Icon, 1, 1, m_fd); /* 3 unknown bytes */ fwrite(tbuf, 1, 3, m_fd); /* 3 junk */ //--------------------------------- String Desc; Desc = Cache.m_Shortname; char* pDesc = w2a((TCHAR*) Desc.c_str()); c = strlen(pDesc); /* 1 string size */ fwrite(&c, 1, 1, m_fd); for (i = 0; pDesc[i]; i++) { fwrite(&pDesc[i], 1, 1, m_fd); /* char */ fwrite(&tbuf[0], 1, 1, m_fd); /* null */ } //--------------------------------- Desc = Cache.m_GsCacheType; Desc += _T(". "); Desc += Cache.m_GsCacheName; Desc += _T(" by "); Desc += Cache.m_GsCacheOwnerName; Desc += _T(". Rating: "); Desc += RatingToStringW(Cache.m_GsCacheDifficulty); Desc += _T("/"); Desc += RatingToStringW(Cache.m_GsCacheTerrain); TCHAR Buffer[20]; Cache.LastFoundText(Buffer); Desc += _T(". Last found: "); Desc += Buffer; pDesc = w2a((TCHAR*) Desc.c_str()); c = strlen(pDesc); /* 1 byte string size */ fwrite(&c, 1, 1, m_fd); for (i = 0; pDesc[i]; i++) { fwrite(&pDesc[i], 1, 1, m_fd); /* char */ fwrite(&tbuf[0], 1, 1, m_fd); /* null */ } //--------------------------------- // Scrap the last string c = strlen(tbuf); /* 1 byte string size */ fwrite(&c, 1, 1, m_fd); for (i = 0; tbuf[i]; i++) { fwrite(&tbuf[i], 1, 1, m_fd); /* char */ fwrite(&tbuf[0], 1, 1, m_fd); /* null */ } }