proto.c

Go to the documentation of this file.
00001 /*
00002  * File Name  : proto.c
00003  */
00004 
00005 /*
00006  * This file is part of kbdupgrade.
00007  *
00008  * kbdupgrade is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * kbdupgrade is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026  
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
00032 #include <sys/types.h>
00033 #include <sys/ioctl.h>
00034 #include <stdio.h>
00035 #include <stdarg.h>
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039 #include <fcntl.h>
00040 #include <termios.h>
00041 
00042 // local include files, between " "
00043 #include "proto.h"
00044 
00045 
00046 //----------------------------------------------------------------------------
00047 // Type Declarations
00048 //----------------------------------------------------------------------------
00049 
00050 
00051 //----------------------------------------------------------------------------
00052 // Global Constants
00053 //----------------------------------------------------------------------------
00054 
00055 static int serial_fd;
00056 int read_timeout = 100;
00057 
00058 
00059 //----------------------------------------------------------------------------
00060 // Static Variables
00061 //----------------------------------------------------------------------------
00062 
00063 
00064 //============================================================================
00065 // Local Function Definitions
00066 //============================================================================
00067 
00068 static int serial_write(uint8_t c);
00069 static int serial_readTimeout(uint8_t *c, int timeout);
00070 static uint8_t serial_read(uint8_t *c);
00071 static uint8_t serial_readEncoded(uint8_t *c);
00072 static void encode_send_byte(uint8_t c);
00073 
00074 
00075 //============================================================================
00076 // Functions Implementation
00077 //============================================================================
00078 
00079 void fatalnum(int num, char *message, ...)
00080 {
00081    char buffer[512];
00082    va_list ap;
00083    va_start(ap, message);
00084    vsprintf(buffer, message, ap);
00085     fprintf(stderr, "Error: %s\n", buffer);
00086    va_end(ap);
00087     exit(num);
00088 }
00089 
00090 
00091 void fatal(char *message, ...)
00092 {
00093    char buffer[512];
00094    va_list ap;
00095    va_start(ap, message);
00096    vsprintf(buffer, message, ap);
00097     fprintf(stderr, "Error: %s\n", buffer);
00098    va_end(ap);
00099     exit(1);
00100 }
00101 
00102 void warning(char *message, ...)
00103 {
00104    char buffer[512];
00105    va_list ap;
00106    va_start(ap, message);
00107    vsprintf(buffer, message, ap);
00108     fprintf(stderr, "Warning: %s\n", buffer);
00109    va_end(ap);
00110 }
00111 
00112 /**
00113  * Send a packet to the microcontroller
00114  *
00115  */
00116 void ionkbd_send_packet(uint8_t cmd, uint8_t length, uint8_t *data)
00117 {
00118     uint8_t i, crc = cmd + length;
00119     serial_write(IONKBD_START);
00120     encode_send_byte(cmd);
00121     encode_send_byte(length);
00122     for (i=0;i<length;i++)
00123     {
00124         crc += data[i];
00125         encode_send_byte(data[i]);
00126     }
00127     encode_send_byte(crc);
00128 }
00129 
00130 /**
00131  * Wait for a response from the microcontroller
00132  *
00133  */
00134 int ionkbd_get_response(uint8_t *command, uint8_t *length, uint8_t *data)
00135 {
00136     uint8_t cmd, len, crc, mycrc, c = 0;
00137     uint8_t i = 0;
00138     while(c != IONKBD_START)
00139     {
00140         if (serial_read(&c)) return 1;
00141     }
00142     if (serial_readEncoded(&cmd)) return 1;
00143     if (serial_readEncoded(&len)) return 1;
00144     mycrc = cmd+len;
00145     while (i<len)
00146     {
00147         if (serial_readEncoded(&data[i])) return 1;
00148         mycrc += data[i++];
00149     }
00150     if (serial_readEncoded(&crc)) return 1;
00151     if (crc != mycrc) 
00152     {
00153         fatal("Response packet CRC failed");
00154     }
00155     *command = cmd;
00156     *length = len;
00157     return 0;
00158 }
00159 
00160 /**
00161  * Send a request to the microcontroller and wait for a response
00162  *
00163  */
00164 int ionkbd_send_request(
00165         uint8_t cmd, 
00166         uint8_t length, 
00167         uint8_t *data, 
00168         uint8_t *rcmd,
00169         uint8_t *rlen,
00170         uint8_t *rdata)
00171 {
00172     ionkbd_send_packet(cmd, length, data);
00173     return ionkbd_get_response(rcmd, rlen, rdata);
00174 }
00175 
00176 /**
00177  * Erase a sector
00178  *
00179  */
00180 int sector_erase(int mode, uint16_t addr)
00181 {
00182     uint8_t data[2], rcmd, rlen, rdata[16];
00183     data[0] = addr>>8;
00184     data[1] = addr&0xFF;
00185     uint8_t req = (mode == MODE_BOOT) ? IONKBD_REQ_ERASE_FLASH_BOOT : 
00186                                         IONKBD_REQ_ERASE_FLASH;
00187     if (ionkbd_send_request(req, 2, data, &rcmd, &rlen, rdata))
00188     {
00189         warning("Micro failed to respond to erase request (0x%02X)", req);
00190         return 1;
00191     }
00192     if (rcmd!=IONKBD_RESP_ERASE) 
00193     {
00194         warning("Invalid erase response");
00195         return 1;
00196     }
00197     if (!rdata[0]) 
00198     {
00199         warning("Flash erase failed");
00200         return 1;
00201     }
00202     return 0;
00203 }
00204 
00205 /**
00206  * Erase the entire flash space
00207  *
00208  */
00209 void micro_erase(int mode, uint16_t start, uint16_t end)
00210 {
00211     uint32_t pos = start;
00212     uint8_t tries;
00213     while (pos < end)
00214     {
00215         printf("Erasing sector @ 0x%04X\r", pos);
00216         tries = 0;
00217         while ((sector_erase(mode, pos)) && (tries<3))
00218         {
00219             tries++;
00220             warning("Erase attempt %d failed", tries);
00221         }
00222         if (tries==3)
00223         { 
00224             fatal("Error erasing sector 0x%04X", pos);
00225         }
00226         pos += 512;
00227     }
00228     printf("\nErasing done\n");
00229 }
00230 
00231 /**
00232  * Program a chunk of flash memory
00233  *
00234  */
00235 int chunk_program(int mode, uint16_t addr, uint8_t len, uint8_t *chunk)
00236 {
00237     uint8_t data[32], rcmd, rlen, rdata[16];
00238     data[0] = addr>>8;
00239     data[1] = addr&0xFF;
00240     uint8_t req = (mode == MODE_BOOT) ? IONKBD_REQ_PROGRAM_FLASH_BOOT : 
00241                                         IONKBD_REQ_PROGRAM_FLASH;
00242     memcpy(&data[2], chunk, len);
00243     if (ionkbd_send_request(req, 2+len, data, &rcmd, &rlen, rdata))
00244     {
00245         fatal("Micro failed to respond to flash request (0x%02X)", req);
00246     }
00247     if (rcmd!=IONKBD_RESP_FLASH) 
00248     {
00249         fatal("Invalid flash response");
00250     }
00251     if (!rdata[0]) 
00252     {
00253         fatal("Flash write failed at 0x%04X", (rdata[1]<<8)|rdata[2]);
00254     }
00255     return 0;
00256 }
00257 
00258 int dr1000_micro_program_application(char* filename)
00259 {
00260     int size, pos=0;
00261     uint8_t bsize, bdata[16];
00262     uint16_t baddr; //, i;
00263 
00264     // open file
00265     FILE *f = fopen(filename, "rb");
00266     // check file size
00267    fseek(f, 0, SEEK_END);
00268    size = ftell(f)-2;
00269    fseek(f, 2, SEEK_SET);
00270     // read chunks
00271     while (pos<size)
00272     {
00273         fread(&bsize, 1, 1, f);
00274         fread(&baddr, 2, 1, f);
00275         baddr = ((baddr&0xFF)<<8) | (baddr>>8);
00276         bsize -= 2;
00277         fread(bdata, bsize, 1, f);
00278         if ((bsize>0x0E) ||
00279             (baddr<DR1000_APPL_ADDR_MIN) ||
00280             (baddr>DR1000_APPL_ADDR_MAX)) 
00281         {
00282             fatal("Invalid firmware params: size: 0x%02X, addr: 0x%04X", 
00283                   bsize, baddr);
00284             exit(1);
00285         }
00286         chunk_program(MODE_APP, baddr, bsize, bdata);
00287         pos += (bsize+3);
00288     }
00289     fclose(f);
00290     return 0;
00291 }
00292 
00293 int dr800_micro_program_application(char* filename)
00294 {
00295     int size, pos=0;
00296     uint8_t bdata[16];
00297 
00298     // open file
00299     FILE *f = fopen(filename, "rb");
00300     // check file size
00301     fseek(f, 0, SEEK_END);
00302     size = ftell(f)-2;
00303     fseek(f, 0, SEEK_SET);
00304     // read chunks
00305     while (pos<size)
00306     {
00307         fread(bdata, 16, 1, f);
00308         printf("Programming address 0x%04X\r", DR800_APPL_ADDR_MIN + pos);
00309         chunk_program(MODE_APP, DR800_APPL_ADDR_MIN + pos, 16, bdata);
00310         pos += 16;
00311     }
00312     printf("\nProgramming done\n");
00313     fclose(f);
00314     return 0;
00315 }
00316 
00317 int dr800_micro_program_bootloader(char* filename)
00318 {
00319     int size, pos=0;
00320     uint8_t bdata[16];
00321 
00322     // open file
00323     FILE *f = fopen(filename, "rb");
00324     // check file size
00325     fseek(f, 0, SEEK_END);
00326     size = ftell(f)-2;
00327     fseek(f, 0, SEEK_SET);
00328     // read chunks
00329     while (pos<size)
00330     {
00331         fread(bdata, 16, 1, f);
00332         printf("Programming address 0x%04X\r", DR800_BOOT_ADDR_MIN + pos);
00333         chunk_program(MODE_BOOT, DR800_BOOT_ADDR_MIN + pos, 16, bdata);
00334         pos += 16;
00335     }
00336     printf("\nProgramming done\n");
00337     fclose(f);
00338     return 0;
00339 }
00340 
00341 int micro_read_devicetype(int mode)
00342 {
00343     uint8_t data[4], rcmd, rlen, rdata[16];
00344     data[0] = DEVICETYPE_ADDR>>8;
00345     data[1] = DEVICETYPE_ADDR&0xFF;
00346     data[2] = 1;
00347     uint8_t req = (mode==MODE_BOOT) ? IONKBD_REQ_READ_FLASH : 
00348                                       IONKBD_REQ_READ_FLASH_BOOT;
00349     if (ionkbd_send_request(req, 3, data, &rcmd, &rlen, rdata))
00350     {
00351         fatal("Micro failed to respond to flash request");
00352     }
00353     if (rcmd!=IONKBD_RESP_READ)
00354     {
00355         fatal("Invalid flash response: 0x%02X", rcmd);
00356     }
00357     return rdata[0];
00358 }
00359 
00360 int micro_write_devicetype(int mode, int devtype)
00361 {
00362     uint8_t data[3], rcmd, rlen, rdata[16];
00363     data[0] = DEVICETYPE_ADDR>>8;
00364     data[1] = DEVICETYPE_ADDR&0xFF;
00365     data[2] = devtype;
00366     uint8_t req = (mode==MODE_BOOT) ? IONKBD_REQ_PROGRAM_FLASH : 
00367                                       IONKBD_REQ_PROGRAM_FLASH_BOOT;
00368     if (ionkbd_send_request(req, 3, data, &rcmd, &rlen, rdata))
00369     {
00370         fatal("Micro failed to respond to flash request");
00371     }
00372     if (rcmd!=IONKBD_RESP_FLASH) 
00373     {
00374         fatal("Invalid flash response");
00375     }
00376     if (!rdata[0]) 
00377     {
00378         fatal("Flash write failed at 0x%04X", (rdata[1]<<8)|rdata[2]);
00379     }
00380     return 0;
00381 }
00382 
00383 int micro_check_battery_charge(uint16_t min_level)
00384 {
00385     uint8_t rcmd, rlen, rdata[16];
00386     uint8_t level, charging;
00387     if (ionkbd_send_request(IONKBD_REQ_GET_BATTERY, 0, NULL, 
00388                             &rcmd, &rlen, rdata))
00389     {
00390         fatal("Micro failed to respond to battery request");
00391     }
00392     if (rcmd!=IONKBD_RESP_BATTERY) 
00393     {
00394         fatal("Invalid flash response");
00395     }
00396     level = rdata[0];
00397     charging = rdata[1];
00398     printf("Micro battery at %d%%%s\n", level, charging?", charging":"");
00399     if (level>=min_level)
00400     {
00401         return 1;
00402     }
00403     else 
00404     {
00405         return ((level>5) && charging);
00406     }
00407 }
00408 
00409 int micro_get_versions(uint16_t *bootloader, uint16_t *application)
00410 {
00411     uint8_t rcmd, rlen, rdata[16];
00412     if (ionkbd_send_request(IONKBD_REQ_GET_VERSION, 0, NULL, 
00413                             &rcmd, &rlen, rdata))
00414     {
00415         fatal("Micro failed to respond to version request");
00416     }
00417     if (rcmd!=IONKBD_RESP_VERSION) 
00418     {
00419         fatal("Invalid version response");
00420     }
00421     *bootloader = (rdata[0]<<8)|rdata[1];
00422     *application = (rdata[2]<<8)|rdata[3];
00423     return 0;
00424 }
00425 
00426 void micro_enter_mode(uint8_t boot)
00427 {
00428     uint8_t data, rcmd, rlen, rdata[16];
00429     uint8_t tries = 0;
00430     int i;
00431 
00432     printf("Entering %s mode.\n", boot ? "app" : "boot");
00433     while (tries<5)
00434     {
00435         for (i=0;i<10;i++)
00436         {
00437             serial_write(IONKBD_START);
00438             usleep(1 * 1000);
00439         }
00440         usleep(5 * 1000);
00441         if (ionkbd_send_request(IONKBD_REQ_GET_STATUS, 0, NULL, 
00442                                 &rcmd, &rlen, rdata))
00443         {
00444             warning("Micro failed to respond to status request");
00445         }
00446         else
00447         {
00448             if (rcmd!=IONKBD_RESP_STATUS) 
00449             {
00450                 warning("Invalid response from status request: 0x%02X", rcmd);
00451             }
00452             else
00453             {
00454                 if ((rdata[0]&1)==boot)
00455                 {
00456                     return;
00457                 }
00458                 data = boot;
00459                 if (ionkbd_send_request(IONKBD_REQ_SET_MODE, 1, &data, 
00460                                         &rcmd, &rlen, rdata))
00461                 {
00462                     warning("Micro failed to respond to set mode request");
00463                 }
00464                 usleep(1000 * 1000);
00465             }
00466         }
00467         tries++;
00468     }
00469     fatal("Failed to enter %s mode.", boot ? "app" : "boot");
00470 }
00471 
00472 int micro_get_mode()
00473 {
00474     uint8_t rcmd, rlen, rdata[16];
00475     if (ionkbd_send_request(IONKBD_REQ_GET_STATUS, 0, NULL, 
00476                             &rcmd, &rlen, rdata))
00477     {
00478         fatal("Micro failed to respond to status request");
00479     }
00480     else
00481     {
00482         if (rcmd!=IONKBD_RESP_STATUS) 
00483         {
00484             fatal("Invalid response from status request: 0x%02X", rcmd);
00485         }
00486         else
00487         {
00488             return (rdata[0]&1);
00489         }
00490     }
00491     return MODE_BOOT;
00492 }
00493 
00494 void micro_get_devicetype(uint8_t *type)
00495 {
00496     uint8_t rcmd, rlen, rdata[16];
00497     if (ionkbd_send_request(IONKBD_REQ_GET_DEVICETYPE, 0, NULL, 
00498                             &rcmd, &rlen, rdata))
00499     {
00500         fatal("Micro failed to respond to devicetype request");
00501     }
00502     if (rcmd!=IONKBD_RESP_DEVICETYPE) 
00503     {
00504         if (rcmd!=IONKBD_RESP_STATUS)
00505         {
00506             fatal("Invalid devicetype response");
00507         }
00508         warning("Received status instead of devicetype respons. Assuming DR1000-series");
00509         rdata[0] = 0;
00510     }
00511     *type = rdata[0];
00512 }
00513 
00514 int gasgauge_get_versions(uint16_t *firmware, uint16_t *hardware)
00515 {
00516     uint8_t rcmd, rlen, rdata[16];
00517     int i;
00518     *firmware = 0x0;
00519     *hardware = 0x0;
00520     for (i=0;i<3;i++)
00521     {
00522         if (!ionkbd_send_request(IONKBD_REQ_GET_GG_VERSION, 0, NULL,
00523                     &rcmd, &rlen, rdata))
00524         {
00525             break;
00526         }
00527         warning("Retrying gas gauge version request");
00528     }
00529     if (i==3)
00530     {
00531         warning("Micro failed to respond to gasgauge version request");
00532         return 1;
00533     }
00534     if ((rcmd != IONKBD_RESP_GG_VERSION) || (rlen != 4))
00535     {
00536         warning("Invalid response to gasgauge version request: %d (%d)",rcmd, rlen);
00537         return 1;
00538     }
00539     *firmware = (rdata[0]*100)|rdata[1];
00540     *hardware = (rdata[2]*100)|rdata[3];
00541     return 0;
00542 }
00543 
00544 int gasgauge_do_command_base(uint8_t *data, uint8_t len)
00545 {
00546     uint8_t rcmd, rlen, rdata[16];
00547     //int i;
00548     if (data[0] > GASGAUGE_STOP) 
00549     {
00550         warning("Invalid gasgauge command %d\n", data[0]);
00551         return 1;
00552     }
00553     /*
00554     printf("GG SEND: cmd: %02X len: %2d data:",IONKBD_REQ_FLASH_GASGAUGE, len);
00555     for (i=0;i<len;i++)
00556         printf(" %02X",data[i]);
00557     printf("\n");
00558     */
00559     if (ionkbd_send_request(IONKBD_REQ_FLASH_GASGAUGE, len, data,
00560                             &rcmd, &rlen, rdata))
00561     {
00562         warning("Micro failed to respond to gasgauge request %d", data[0]);
00563         return 1;
00564     }
00565     if ((rcmd == IONKBD_RESP_GASGAUGE) && (rlen > 0) &&
00566         (rdata[0] == data[0]))
00567     {
00568         if (rdata[1] == 0)
00569         {
00570             warning("Gasgauge request %d failed after %d tries", 
00571                     data[0], rdata[2]);
00572             return 1;
00573         }
00574         else
00575         {
00576             //printf("Gasgauge request %d succeeded after %d tries\n", 
00577             //        data[0], rdata[2]);
00578             return 0;
00579         }
00580     }
00581     else
00582     {
00583         warning("Invalid respond to gasgauge request %d", data[0]);
00584         return 1;
00585     }
00586     return 0;
00587 }
00588 
00589 int gasgauge_do_command(uint8_t command)
00590 {
00591     return gasgauge_do_command_base(&command, 1);
00592 }
00593 
00594 int gasgauge_do_setup_row(uint8_t start, uint8_t *data, uint8_t len)
00595 {
00596     uint8_t buf[16];
00597     int i;
00598     buf[0] = GASGAUGE_SETUP_ROW;
00599     buf[1] = start;
00600     for (i=0;i<len;i++)
00601         buf[2+i] = data[i];
00602     return gasgauge_do_command_base(buf, 2+len);
00603 }
00604 
00605 int gasgauge_do_program_row(uint8_t row)
00606 {
00607     uint8_t buf[2];
00608     buf[0] = GASGAUGE_PROGRAM_ROW;
00609     buf[1] = row;
00610     return gasgauge_do_command_base(buf, 2);
00611 }
00612 
00613 int gasgauge_flash(char *filename)
00614 {
00615     uint8_t image[1024];
00616     uint8_t *imgptr;
00617     int row, i;
00618     int attempts=0;
00619     FILE *f;
00620 
00621     read_timeout = 1000;
00622 
00623     printf("Loading gasgauge firmware\n");
00624     // open file
00625     f = fopen(filename, "rb");
00626     if (!f)
00627     {
00628         warning("Couldn't open firmware file");
00629         return 1;
00630     }
00631     // check file size
00632    fseek(f, 0, SEEK_END);
00633    if (ftell(f)!=1025)
00634     {
00635         warning("Invalid firmware size");
00636         return 1;
00637     }
00638    fseek(f, 0, SEEK_SET);
00639     // read file
00640     fread(image, 1024, 1, f);
00641     fclose(f);
00642 
00643     printf("Initialising gasgauge programming\n");
00644     // Step 1 - Init
00645     for (i=0;i<3;i++)
00646     {
00647         if (!gasgauge_do_command(GASGAUGE_INIT))
00648             break;
00649         warning("Retrying gas gauge init");
00650     }
00651     if (i==3)
00652     {
00653         warning("Failed to initialise gas gauge programming");
00654         return 1;
00655     }
00656     printf("starting\n");
00657     // Step 2 - Start
00658     for (i=0;i<3;i++)
00659     {
00660         if (!gasgauge_do_command(GASGAUGE_START))
00661             break;
00662         warning("Retrying gas gauge start");
00663     }
00664     if (i==3)
00665     {
00666         warning("Failed to start gas gauge programming");
00667         return 1;
00668     }
00669     printf("saving settings\n");
00670     // Step 3 - Save Settings
00671     while (gasgauge_do_command(GASGAUGE_SAVE_SETTINGS))
00672     {
00673         warning("Failed to save gasgauge settings, retrying");
00674     }
00675     // main program loop
00676     while (attempts<20)
00677     {
00678         imgptr = image;
00679         printf("Starting flash loop (attempt %d)\n",attempts+1);
00680         printf("Erasing gasgauge flash\n");
00681         // Step 4 - Erase
00682         if (gasgauge_do_command(GASGAUGE_ERASE))
00683         {
00684             warning("Failed to erase gasgauge flash, restarting");
00685             continue;
00686         }
00687         // program rows
00688         for (row=0;row<32;row++) 
00689         {
00690             // Step 5 - Setup row
00691             printf("Setting up row  %2d\n",row);
00692             for (i=0;i<4;i++)
00693             {
00694                 gasgauge_do_setup_row(i*8, imgptr, 8);
00695                 imgptr += 8;
00696             }
00697 
00698             // Step 6 - Program row
00699             printf("Programming row %2d\n", row);
00700             if (gasgauge_do_program_row(row))
00701             {
00702                 warning("Failed programming, restarting");
00703                 break;
00704             }
00705         }
00706         // check if we're done
00707         if (row==32)
00708         {
00709             printf("Restoring settings\n");
00710             // Step 7 - Restore Settings
00711             if (!gasgauge_do_command(GASGAUGE_RESTORE_SETTINGS))
00712             {
00713                 printf("All OK, finishing\n");
00714                 break;
00715             }
00716         }
00717         attempts++;
00718     }
00719 
00720     if (attempts==20)
00721     {
00722         warning("Failed to program gasgauge");
00723         return 1;
00724     }
00725 
00726     printf("Stopping\n");
00727     // Step 8 - Stop
00728     if (gasgauge_do_command(GASGAUGE_STOP))
00729     {
00730         warning("Failed to stop gas gauge programming");
00731         return 1;
00732     }
00733     
00734     return 0;
00735 }
00736 
00737 void port_open(char* name, int flags, int speed)
00738 {
00739     struct termios t;
00740     
00741     if ((serial_fd = open(name, O_RDWR | O_NOCTTY)) < 0) 
00742     {
00743         fatal("Can't open device %s", name);
00744     }
00745 
00746     tcgetattr(serial_fd, &t);
00747 
00748     t.c_cflag = flags | CREAD | HUPCL | CLOCAL;
00749     t.c_iflag = IGNBRK | IGNPAR;
00750     t.c_oflag = 0;
00751     t.c_lflag = 0;
00752     t.c_cc[VMIN ] = 1;
00753     t.c_cc[VTIME] = 0;
00754 
00755     cfsetispeed(&t, speed);
00756     cfsetospeed(&t, speed);
00757     tcflush(serial_fd, TCIFLUSH);
00758     tcsetattr(serial_fd, TCSANOW, &t);
00759 }
00760 
00761 
00762 //============================================================================
00763 // Local Functions Implementation
00764 //============================================================================
00765 
00766 /**
00767  * Write a character to the serial port
00768  *
00769  */
00770 static int serial_write(uint8_t c)
00771 {
00772     write(serial_fd, &c, 1);
00773     return 0;
00774 }
00775 
00776 /**
00777  * Wait for a character from the serial port, fail after specified ms
00778  *
00779  */
00780 static int serial_readTimeout(uint8_t *c, int timeout)
00781 {
00782     struct timeval tv;
00783     fd_set set;
00784     
00785     tv.tv_sec = 0;
00786     tv.tv_usec = timeout * 1000;
00787 
00788     FD_ZERO(&set);
00789     FD_SET(serial_fd, &set);
00790 
00791     if (!select(serial_fd+1, &set, NULL, NULL, &tv)) return -1;
00792     if (read(serial_fd, c, 1) != 1) return -1;
00793 
00794     return 0;
00795 }
00796 
00797 /**
00798  * Read a character and fail on timeout
00799  *
00800  */
00801 static uint8_t serial_read(uint8_t *c)
00802 {
00803     if (serial_readTimeout(c, read_timeout)) 
00804     {
00805         warning("Timeout waiting for response");
00806         return 1;
00807     }
00808     return 0;
00809 }
00810 
00811 /**
00812  * Read an escaped character from the serial port
00813  *
00814  */
00815 static uint8_t serial_readEncoded(uint8_t *c)
00816 {
00817     if (serial_read(c)) return 1;
00818     if (*c==IONKBD_ESC)
00819     {
00820         if (serial_read(c)) return 1;
00821         switch (*c)
00822         {
00823             case IONKBD_ESC_START:
00824                 *c = IONKBD_START;
00825                 break;
00826             case IONKBD_ESC_ESC:
00827                 *c = IONKBD_ESC;
00828                 break;
00829             default:
00830                 return 1;
00831         }
00832     }
00833     return 0;
00834 }
00835 
00836 /**
00837  * Encode a byte and send it to the microcontroller 
00838  *
00839  */
00840 static void encode_send_byte(uint8_t c)
00841 {
00842     if (c==IONKBD_START)
00843     {
00844         serial_write(IONKBD_ESC);
00845         serial_write(IONKBD_ESC_START);
00846     }
00847     else if (c==IONKBD_ESC)
00848     {
00849         serial_write(IONKBD_ESC);
00850         serial_write(IONKBD_ESC_ESC);
00851     }
00852     else 
00853     {
00854         serial_write(c);
00855     }
00856 }
Generated by  doxygen 1.6.2-20100208