dataXferImpl.c
Go to the documentation of this file.00001 #include "dataXferImpl.h"
00002 #include <string.h>
00003
00008
00009
00010
00012 static CMD_STATE cmdState;
00013
00015 static CMD_OUTPUT cmdOutput;
00016
00019 void resetCommandFindMachine()
00020 {
00021 cmdState = STATE_CMD_START;
00022 cmdOutput = OUTPUT_CMD_NONE;
00023 }
00024
00062 CMD_OUTPUT stepCommandFindMachine(char c_inChar, char* c_outChar)
00063 {
00064 switch (cmdState)
00065 {
00066 case STATE_CMD_START :
00067 if (c_inChar != CMD_TOKEN) {
00068
00069 *c_outChar = c_inChar;
00070 cmdOutput = OUTPUT_CMD_CHAR;
00071 } else {
00072 cmdState = STATE_CMD_WAIT1;
00073 cmdOutput = OUTPUT_CMD_NONE;
00074 }
00075 break;
00076
00077
00078 case STATE_CMD_WAIT1 :
00079 switch (c_inChar) {
00080 case CMD_TOKEN :
00081
00082 cmdState = STATE_CMD_WAIT2;
00083 break;
00084
00085 case ESCAPED_CMD :
00086
00087 *c_outChar = CMD_TOKEN;
00088 cmdOutput = OUTPUT_CMD_CHAR;
00089 cmdState = STATE_CMD_START;
00090 break;
00091
00092 default :
00093
00094 *c_outChar = c_inChar;
00095 cmdOutput = OUTPUT_CMD_CMD;
00096 cmdState = STATE_CMD_START;
00097 break;
00098 }
00099 break;
00100
00101 case STATE_CMD_WAIT2 :
00102 switch (c_inChar) {
00103 case ESCAPED_CMD :
00104
00105
00106 cmdOutput = OUTPUT_CMD_CMD;
00107 cmdState = STATE_CMD_START;
00108 *c_outChar = CMD_TOKEN;
00109 break;
00110
00111 case CMD_TOKEN :
00112
00113
00114
00115
00116 cmdOutput = OUTPUT_CMD_REPEATED_WAIT;
00117 break;
00118
00119 default :
00120
00121
00122 *c_outChar = c_inChar;
00123 cmdOutput = OUTPUT_CMD_REPEATED_CMD;
00124 cmdState = STATE_CMD_START;
00125 break;
00126
00127 }
00128 break;
00129
00130 default:
00131
00132 ASSERT(FALSE);
00133 break;
00134 }
00135
00136 return cmdOutput;
00137 }
00139
00140
00141
00142 XFER_VAR xferVar[NUM_XFER_VARS];
00143 uint8 au8_xferVarWriteable[NUM_XFER_VARS/8 + ((NUM_XFER_VARS % 8) > 0)];
00144
00145
00146
00147
00149
00150
00152 static RECEIVE_STATE receiveState;
00153
00156 static char c_outChar;
00157
00161 static uint u_index;
00162
00165 static RECEIVE_ERROR receiveError;
00166
00167 #ifndef __PIC__
00170 static BOOL b_isSpec;
00171 #define B_IS_SPEC b_isSpec
00172 #else
00173
00174 #define B_IS_SPEC 0
00175 #endif
00176
00179 RECEIVE_STATE getReceiveMachineState()
00180 {
00181 return receiveState;
00182 }
00183
00186 char getReceiveMachineOutChar()
00187 {
00188 return c_outChar;
00189 }
00190
00193 uint getReceiveMachineIndex()
00194 {
00195 return u_index;
00196 }
00197
00198
00202 RECEIVE_ERROR getReceiveMachineError()
00203 {
00204 RECEIVE_ERROR re = receiveError;
00205 receiveError = ERR_NONE;
00206 return re;
00207 }
00208
00209
00210 #if !defined(__PIC__) || defined(__DOXYGEN__)
00214 BOOL getReceiveMachineIsSpec()
00215 {
00216 return b_isSpec;
00217 }
00218 #endif
00219
00220
00224 void resetReceiveMachine()
00225 {
00226 receiveState = STATE_RECV_START;
00227 receiveError = ERR_NONE;
00228
00229
00230 resetCommandFindMachine();
00231 }
00232
00233
00236 void clearReceiveMachineError() {
00237 receiveError = ERR_NONE;
00238 }
00239
00240
00243 void clearReceiveStruct() {
00244 memset(xferVar, 0, sizeof(xferVar));
00245 memset(au8_xferVarWriteable, 0, sizeof(au8_xferVarWriteable));
00246 }
00247
00255 BOOL isReceiveMachineChar(char* c_receivedChar)
00256 {
00257 *c_receivedChar = c_outChar;
00258 return ( (receiveState == STATE_RECV_START) && (receiveError == ERR_NONE) &&
00259 (u_index == CHAR_RECEIVED_INDEX) );
00260 }
00261
00262
00270 BOOL isReceiveMachineData(uint* u_receivedIndex)
00271 {
00272 *u_receivedIndex = u_index;
00273 return ( (receiveState == STATE_RECV_START) && (receiveError == ERR_NONE) &&
00274 (u_index != CHAR_RECEIVED_INDEX) && !B_IS_SPEC);
00275 }
00276
00277
00278 #if !defined(__PIC__) || defined(__DOXYGEN__)
00279
00286 BOOL isReceiveMachineSpec(uint* u_receivedIndex)
00287 {
00288 *u_receivedIndex = u_index;
00289 return ( (receiveState == STATE_RECV_START) && (receiveError == ERR_NONE) &&
00290 (u_index != CHAR_RECEIVED_INDEX) && B_IS_SPEC);
00291 }
00292 #endif
00293
00294
00299 uint getVarIndex(char c_cmd)
00300 {
00301 return ((unsigned char) c_cmd) >> VAR_SIZE_BITS;
00302 }
00303
00308 uint getVarLength(char c_cmd)
00309 {
00310 return (c_cmd & VAR_SIZE_MASK) + 1;
00311 }
00312
00319 static uint8* validateIndex() {
00320 uint8* pu8_data = NULL;
00321
00322
00323 if (u_index >= NUM_XFER_VARS) {
00324 receiveError = ERR_INDEX_TOO_HIGH;
00325 receiveState = STATE_RECV_START;
00326 return NULL;
00327 }
00328
00329
00330
00331 pu8_data = xferVar[u_index].pu8_data;
00332
00333 if (pu8_data == NULL) {
00334 receiveError = ERR_UNSPECIFIED_INDEX;
00335 receiveState = STATE_RECV_START;
00336 return NULL;
00337 }
00338
00339
00340 #ifdef __PIC__
00341 if (!isVarWriteable(u_index)) {
00342 receiveError = ERR_READ_ONLY_VAR;
00343 receiveState = STATE_RECV_START;
00344 return NULL;
00345 }
00346 #endif
00347
00348
00349 return pu8_data;
00350 }
00351
00356 void assignBit(uint u_index, BOOL b_bitVal) {
00357
00358 uint u_byteIndex = u_index / 8;
00359
00360 uint8 u8_mask = 1 << (u_index % 8);
00361
00362 if (b_bitVal)
00363 au8_xferVarWriteable[u_byteIndex] |= u8_mask;
00364 else
00365 au8_xferVarWriteable[u_byteIndex] &= ~u8_mask;
00366 }
00367
00375 BOOL isVarWriteable(uint u_index) {
00376
00377 uint u_byteIndex = u_index / 8;
00378
00379 uint8 u8_mask = 1 << (u_index % 8);
00380
00381 return (au8_xferVarWriteable[u_byteIndex] & u8_mask) != 0;
00382 }
00383
00390 static BOOL validateLength(uint u_varLength) {
00391 if (xferVar[u_index].u8_size != (u_varLength - 1)) {
00392 receiveError = ERR_VAR_SIZE_MISMATCH;
00393 receiveState = STATE_RECV_START;
00394 return FALSE;
00395 } else {
00396 return TRUE;
00397 }
00398 }
00399
00400 #ifndef __PIC__
00403 static uint8 au8_varSpecData[256 + 3];
00404
00406 static uint u_specLength;
00407
00411 static void parseVarSpec() {
00412 uint u_size;
00413 size_t st_len;
00414 XFER_VAR* pXferVar = xferVar + u_index;
00415 char* psz_s;
00416
00417
00418 if (pXferVar->pu8_data != NULL) {
00419 free(pXferVar->pu8_data);
00420 free(pXferVar->psz_format);
00421 free(pXferVar->psz_name);
00422 free(pXferVar->psz_desc);
00423 }
00424
00425
00426
00427 u_size = pXferVar->u8_size = au8_varSpecData[0];
00428 u_size++;
00429 pXferVar->pu8_data = (uint8*) malloc(sizeof(uint8)*u_size);
00430
00431
00432 ASSERT(u_specLength + 2 < sizeof(au8_varSpecData));
00433 au8_varSpecData[u_specLength + 0] = 0;
00434 au8_varSpecData[u_specLength + 1] = 0;
00435 au8_varSpecData[u_specLength + 2] = 0;
00436
00437
00438 psz_s = (char*) au8_varSpecData + 1;
00439 st_len = strlen(psz_s) + 1;
00440 pXferVar->psz_format = (char*) malloc(sizeof(char)*st_len);
00441 strcpy(pXferVar->psz_format, psz_s);
00442 psz_s += st_len;
00443 ASSERT(((uint8*) psz_s) < au8_varSpecData + sizeof(au8_varSpecData));
00444
00445
00446 st_len = strlen(psz_s) + 1;
00447 pXferVar->psz_name = (char*) malloc(sizeof(char)*st_len);
00448 strcpy(pXferVar->psz_name, psz_s);
00449 psz_s += st_len;
00450 ASSERT(((uint8*) psz_s) < au8_varSpecData + sizeof(au8_varSpecData));
00451
00452
00453 st_len = strlen(psz_s) + 1;
00454 pXferVar->psz_desc = (char*) malloc(sizeof(char)*st_len);
00455 strcpy(pXferVar->psz_desc, psz_s);
00456 psz_s += st_len;
00457 ASSERT(((uint8*) psz_s) < au8_varSpecData + sizeof(au8_varSpecData));
00458 }
00459 #endif
00460
00475 RECEIVE_ERROR stepReceiveMachine(char c_inChar, BOOL b_isTimeout)
00476 {
00477
00478 CMD_OUTPUT cmdOutput;
00479
00480 static uint u_varLength;
00481
00482 static uint8* pu8_data = NULL;
00483 #ifndef __PIC__
00484
00485 static char c_lastCommand;
00486 #endif
00487
00488
00489
00490
00491 if ((receiveState != STATE_RECV_START) && b_isTimeout) {
00492
00493
00494 resetReceiveMachine();
00495 receiveError = ERR_TIMEOUT;
00496 }
00497
00498
00499
00500 cmdOutput = stepCommandFindMachine(c_inChar, &c_outChar);
00501
00502
00503
00504
00505 switch (cmdOutput) {
00506 case OUTPUT_CMD_NONE :
00507 if (receiveState == STATE_RECV_START) {
00508 receiveState = STATE_RECV_CMD_WAIT;
00509 }
00510 return receiveError;
00511
00512 case OUTPUT_CMD_REPEATED_CMD :
00513
00514
00515 receiveError = ERR_REPEATED_CMD;
00516 cmdOutput = OUTPUT_CMD_CMD;
00517 break;
00518
00519 case OUTPUT_CMD_REPEATED_WAIT :
00520
00521
00522 receiveError = ERR_REPEATED_CMD;
00523 return receiveError;
00524
00525 case OUTPUT_CMD_CMD :
00526
00527
00528
00529 if (receiveState != STATE_RECV_CMD_WAIT) {
00530 receiveError = ERR_INTERRUPTED_CMD;
00531 receiveState = STATE_RECV_CMD_WAIT;
00532 }
00533 break;
00534
00535 case OUTPUT_CMD_CHAR :
00536
00537 break;
00538
00539 default :
00540 ASSERT(FALSE);
00541 break;
00542 }
00543
00544
00545
00546 switch (receiveState)
00547 {
00548 case STATE_RECV_START:
00549 switch (cmdOutput)
00550 {
00551 case OUTPUT_CMD_CHAR :
00552
00553
00554
00555 if (receiveError != ERR_TIMEOUT)
00556 receiveError = ERR_NONE;
00557 u_index = CHAR_RECEIVED_INDEX;
00558 break;
00559
00560 default :
00561
00562
00563 ASSERT(FALSE);
00564 break;
00565 }
00566 break;
00567
00568 case STATE_RECV_CMD_WAIT :
00569 switch (cmdOutput)
00570 {
00571 case OUTPUT_CMD_CHAR :
00572
00573
00574 ASSERT(c_outChar == CMD_TOKEN);
00575 receiveState = STATE_RECV_START;
00576 receiveError = ERR_NONE;
00577 u_index = CHAR_RECEIVED_INDEX;
00578 break;
00579
00580 case OUTPUT_CMD_CMD :
00581
00582 switch (c_outChar)
00583 {
00584 case CMD_LONG_VAR :
00585 receiveState = STATE_RECV_LONG_INDEX;
00586 break;
00587
00588 case CMD_SEND_ONLY :
00589 case CMD_SEND_RECEIVE_VAR :
00590 #ifdef __PIC__
00591
00592 receiveState = STATE_RECV_START;
00593 receiveError = ERR_PIC_VAR_SPEC;
00594 break;
00595 #else
00596
00597 c_lastCommand = c_outChar;
00598 receiveState = STATE_RECV_SPEC_INDEX;
00599 break;
00600 #endif
00601
00602 case ESCAPED_CMD :
00603
00604 ASSERT(FALSE);
00605 break;
00606
00607 default :
00608
00609
00610 u_index = getVarIndex(c_outChar);
00611 u_varLength = getVarLength(c_outChar);
00612 #ifndef __PIC__
00613 b_isSpec = FALSE;
00614 #endif
00615
00616 pu8_data = validateIndex();
00617
00618 if (pu8_data == NULL)
00619 break;
00620
00621 if (!validateLength(u_varLength))
00622 break;
00623
00624
00625 receiveState = STATE_RECV_READ_BYTES;
00626 break;
00627 }
00628 break;
00629
00630 default :
00631 ASSERT(FALSE);
00632 break;
00633 }
00634 break;
00635
00636 case STATE_RECV_READ_BYTES :
00637
00638 *pu8_data++ = c_outChar;
00639
00640
00641 if (--u_varLength == 0)
00642 {
00643 receiveError = ERR_NONE;
00644 receiveState = STATE_RECV_START;
00645 #ifndef __PIC__
00646 if (b_isSpec)
00647 parseVarSpec();
00648 #endif
00649 }
00650 break;
00651
00652 case STATE_RECV_LONG_INDEX :
00653
00654 u_index = c_outChar;
00655 #ifndef __PIC__
00656 b_isSpec = FALSE;
00657 #endif
00658
00659 pu8_data = validateIndex();
00660
00661 if (pu8_data == NULL)
00662 break;
00663
00664 receiveState = STATE_RECV_LONG_LENGTH;
00665 break;
00666
00667 #ifndef __PIC__
00668 case STATE_RECV_SPEC_INDEX :
00669
00670 u_index = c_outChar;
00671 b_isSpec = TRUE;
00672
00673 pu8_data = au8_varSpecData;
00674
00675 ASSERT( (c_lastCommand == CMD_SEND_ONLY) ||
00676 (c_lastCommand == CMD_SEND_RECEIVE_VAR) );
00677 assignBit(u_index, c_lastCommand == CMD_SEND_RECEIVE_VAR);
00678
00679 receiveState = STATE_RECV_LONG_LENGTH;
00680 break;
00681 #endif
00682
00683 case STATE_RECV_LONG_LENGTH :
00684
00685
00686
00687
00688
00689
00690
00691 u_varLength = ((uint) ((uint8) c_outChar)) + 1;
00692
00693 if (!B_IS_SPEC && !validateLength(u_varLength))
00694 break;
00695 #ifndef __PIC__
00696 else
00697
00698
00699 u_specLength = u_varLength;
00700 #endif
00701
00702 receiveState = STATE_RECV_READ_BYTES;
00703 break;
00704
00705 default:
00706 ASSERT(FALSE);
00707 break;
00708 }
00709
00710 return receiveError;
00711 }
00713
00714
00717 static const char* apsz_errorDesc[NUM_ERROR_CODES] = {
00718 "no error",
00719 "repeated command",
00720 "timeout",
00721 "interrupted command",
00722 "unspecified index",
00723 "index too high",
00724 "variable size mismatch",
00725 "read only variable",
00726 "illegal variable specification",
00727 };
00728
00730 const char* getReceiveErrorString() {
00731 ASSERT( (receiveError > 0) && (receiveError < NUM_ERROR_CODES) );
00732 return apsz_errorDesc[receiveError];
00733 }