Using Tools: 9.3 pccom: File Transfer Protocol of PCCOM

Up: GEOS SDK TechDocs | Up | Prev: 9.2 Running PCCOM on the Target | Next: 10 pcget

If you need to create your own file transfer program or module, you can use the basic PCCOM commands and a special transfer protocol to send or receive files over the serial link. This is useful, for example, if you have an existing Windows or DOS program to which you would like the to add the ability to transfer files to or from the Zoomer (or another unit running PCCOM).

Sending a File to the Remote Machine

Sending a file to the remote machine involves the steps below. A file may be sent by any program that can access the serial port.

  1. Notify PCCOM that a file is on its way.
    Send the Send File escape character sequence to the serial port, notifying PCCOM that a file is about to be sent to it. The escape sequence is <Esc>XF<Ctrl-A> (<Esc>XF<0x01>).
  2. Send the destination file name.
    Send the name PCCOM should use for the file when saving it. The name is a string of sequential characters ending with a null byte. If sending the file to the target machine's target directory, this will just be the file's name; if sending to a different directory, this string should instead be the full pathname. Thus, to do the equivalent of "pcsend yuyuhack.sho /d:b:\geoworks\document", this string would consist of "b:\geoworks\document\yuyuhack.sho".
    If a timeout occurs while sending the filename, a NAK_QUIT will be returned and the remote machine will abort the file-send operation.
  3. Wait for acknowledgment of the name transfer.
    PCCOM will send a 0xFF character or a SYNC byte to acknowledge acceptance of the file name. If you do not receive this character, an error has likely occurred.
  4. Send the file size.
    The file size should be encoded as a dword value. Send the low byte first.
  5. Send a packet.
    Once you have received the SYNC or 0xFF byte, you can safely begin sending packets of data to PCCOM. A packet has the following format (sequence of bytes, with the first listed being the first sent):
  6. BLOCK_START				( = 1 )
    data
    BLOCK_END				( = 2 )
    CRC				( checksum value )

    The data between BLOCK_START and the checksum value (CRC) may be up to 1 K. In order to avoid PCCOM confusion between a normal data byte and a BLOCK_START or BLOCK_END, a third element--BLOCK_QUOTE--is used.

    Any time you have a data byte equal to 1, 2, or 3, you must quote it by inserting a BLOCK_QUOTE byte before it and then adding three to its value. Thus, if you had a data sequence consisting of the following

    100, 42, 2, 3, 16

    you would send the following sequence of bytes to transfer the data:

    <Esc>FX1					( alert PCCOM a
    					  file is coming )
    <null-terminated file name>
    <wait for SYNC byte>
    BLOCK_START					( = 1 )
    100
    42
    BLOCK_QUOTE					( = 3 )
    5					( = 2 + 3 )
    BLOCK_QUOTE					( = 3 )
    6					( = 3 + 3 )
    16
    BLOCK_END					( = 2 )
    CRC					( checksum value )

    The CRC word is two bytes of checksum value as calculated using the table and code shown in "Calculating Checksum Values," below. The CRC value is based upon the data bytes only. The low byte is transmitted first. You should use this code to ensure that your checksums will match PCCOM's.

  7. Optionally, the first packet may contain the filename and file size.
    In the first (and only the first) packet, it is possible to send a data block containing the file's name. If such a block is received by pccom or the PCCom library, then this filename will take precedence over the filename that was sent before the packets. Since the first filename may have been corrupted by noise, this provides a surer backup. The file size is passed as a dword value, low byte first.
  8. This data block should have the following data:

    "!PCCom File Transfer Filename Block! "  <no NULL>
    <null-terminated file name> <null> <dword file size>

    The CRC for this block should be one higher than it would normally be--this signals that this block is of this special format.

  9. Wait for a SYNC byte acknowledgment.
    After each packet, you must make sure PCCOM responds positively with another SYNC byte. If the SYNC is not received, the packet likely failed. If the packet succeeded, continue sending packets as above (waiting for a SYNC after each) until done transferring the data.
  10. If, instead of receiving a SYNC value, you receive a NAK_QUIT value, the target machine has aborted to an unrecoverable error, and there is little point in continuing to send data over the serial line.

    A NAK byte signals that the target machine had an error but that it may be possible to continue the send operation by re-sending the block.

    When sending an optional filename packet, as described in step six, normally one does not re-send the packet it if it fails to send.

  11. Repeat steps five and seven as many times as necessary to transfer the entire file.
  12. Send two zero bytes.
    To make it absolutely clear that the file transfer has finished, send two zero bytes.

Retrieving a File Remotely

Retrieving a file from a machine running PCCOM is straightforward and uses the same file transfer protocol shown above for sending a file. The sequence of commands is different, however, and is listed below.

  1. Notify PCCOM that you're getting a file.
    Send the Get File escape character sequence to the serial port, notifying PCCOM that it should get ready to send a file. The escape sequence is <Esc>XF<Ctrl-D> (<Esc>XF<0x04>).
  2. Send the source file name.
    Send the name of the file to be retrieved. The name is a string of sequential characters ending with a null byte.
  3. Wait for SYNC byte signifying acknowledgment of the name transfer.
    PCCOM will send a 0xFF character or a SYNC byte to acknowledge acceptance of the file name. If you do not receive this character, an error has likely occurred (e.g., the file name wasn't successfully transmitted).
  4. Wait for another SYNC byte signifying file found.
    PCCOM will send a SYNC byte to acknowledge that the desired file was found.
  5. Wait for RECV_COMMAND byte.
    PCCOM will send a RECV_COMMAND byte signifying the file was successfully opened.
  6. Receive destination file name.
    This null-terminated string contains the place to write the file on the host machine. This path string may be up to size PATH_BUFFER_SIZE (defined in file.h).
  7. Send a SYNC byte to acknowledge receipt of the destination file name.
    By sending a SYNC byte, the host acknowledges that it has received the destination file name and is ready to continue the transfer.
  8. Receive the file size.
    The next data received will be the file's size, expressed as a dword, with the low byte sent first.
  9. Receive packets.
    After you receive thefile size from PCCOM, you will begin receiving data packets. Each packet you receive will follow the same format as described above for sending a file. Be aware of the BLOCK_QUOTE requirements when receiving the data (described in sending a file).
  10. You will receive a checksum word at the end of each block's data. If the sent checksum matches the one you calculate from the received data, send a SYNC byte to the serial port (0xFF); otherwise send a NAK value. Calculate all your checksum values with the table and code presented in "Calculating Checksum Values," below.

    When retrieving files, there will never be a file name packet such as described in step six of the file-sending procedure. Thus, you need not check to see whether a block whose CRC is off by one in fact contains a file name; you should not acknowledge this block.

  11. Receive two zero bytes.
    These make it clear that the file transfer has been completed.
  12. Send an ACK byte.
    This acknowledges the end of the file transfer.
  13. Repeat steps 4 through 11 until END_COMMAND byte received.
    If the filename passed to pcget contained wildcard characters and there is more than one matching file, PCCom will send all of them, using the protocol outlined in steps 4 through 11. If in step 4 an END_COMMAND byte is received instead of a SYNC byte, all files have been sent.

Calculating Checksum Values

The CRC word that accompanies each block of transferred data must be calculated using the same code as PCCOM or you will probably have only unsuccessful transmissions. The code used by PCCOM is shown on the next page, and you may include it in your own file transfer program. PCSEND, PCGET, and PCS also use the same checksum calculation code. This checksum should be based only on the data itself; do not include the BLOCK_START, BLOCK_QUOTE, or BLOCK_END characters in your calculations.

Code Display 9-1 PCCOM Checksums

/**********************************************************************
 *		CalcCRC						*
 **********************************************************************
 * SUMMARY:		Calculate the CRC on a block of data.
 * PASS:		char *buf		Pointer to the data buffer
 *		short size		Size of the data buffer
 *		short checksum		Previous checksum (0 at first)
 * RETURN:		CRC value (2 bytes)
 **********************************************************************/
short	crcTable[] = { 
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
unsigned short		IncCRC(unsigned short crc, char c){
    return ((crc << 8) ^ crcTable[((crc >> 8) ^ c) & 0xff]);
}
short		CalcCRC(char *buf, short size, short checksum){
/* The CRC is for the data part of the packet only. 
 * The CRC value is passed low byte first. */
    for (;size > 0; size--){
 	checksum = IncCRC(checksum, *buf++);
    }
    return checksum;
}

Testing the Connection

If the other side of a PCCom connection exits, you will get no notification. One way to test the connection to make sure that's still open is to send a <Esc>AKon! command. This requests that the other side of the connection send an <Esc>ACK at completion of each command. Note that the other side will try to acknowledge of the <Esc>AKon!, so that gives you a quick indicator that the other side is active. Assuming you don't want to stay in this mode, send an <Esc>AKoff!.


Up: GEOS SDK TechDocs | Up | Prev: 9.2 Running PCCOM on the Target | Next: 10 pcget