Basics
From PyGarmin
Almost every model of Garmin receiver implements a slightly different protocol. They have many things in common, but there are minor differences. For example, some receivers can display icons, and they therefore transmit waypoints which have an extra 'symbol' field, which is not used in other models. Others don't use icons, but do store altitude. And so forth. You need to get the protocol right for your particular model.
This makes matters more complicated, but at least these things are well documented by Garmin. The specification includes a big table which details, for each product type, what protocol it uses for basic commands, what it uses for downloading waypoints, what it uses for downloading routes, and so forth.
I have created Python classes for each of the protocols listed in the spec, and for each of the data types. Well, most of them. The big table becomes, in Python, a mapping from the Garmin product ID to the set of relevant classes. This means that, while there are a large number of classes defined in the source, only a few of them will ever be used by any given receiver. The classes are all given names based on those used in the specification, so look at the spec if you want to know more about the classes.
The class garmin.Garmin will connect to your GPS, read its product ID and software version, and then look up the appropriate classes in the table. It creates instances of the protocol classes and notes the datatype classes for each type of data used in the transmisisons. It also has some friendly methods like 'getWaypoints', which do what you would expect. What you get back when you call this is a list of objects, each of which is an instance of a class derived from garmin.Waypoint, but the precise type of the objects will depend on the GPS you're talking to.
Now have a look at some Example code.

