Main Page   Modules   Alphabetical List   Data Structures   File List   Related Pages  

packet.c

00001 /*packet.c 
00002 universal packet parsing functions for the Pc-pack's coprocessor.
00003 2002 Nathan Gustavson
00004 Emac.inc of Carbondale 
00005 */
00006 
00007 #include <sys/types.h>
00008 #include <asm/types.h>
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <string.h>
00012 #define LIBCOMP /*don't include extern declarations*/
00013 #include "../includes/packet.h"
00014 
00015 
00016 /*function prototypes*/
00017 
00018 int PcpkParsePacket(char *, PcpkPacket *);
00019 PcpkHeader PcpkParseHeader(char *, PcpkPacket *);
00020 int PcpkParseData(char *, PcpkPacket *);
00021 int PcpkPacketAssign(PcpkPacket *);
00022 unsigned int Pcpkonescount(unsigned char);
00023 int PcpkPacketDestroy (PcpkPacket *);
00024 char *cutbyte(char *stringin, __u8 *cutbbuffer);
00025 unsigned short *cutword(char *stringin, __u8 *cutbbuffer);
00026 char *PcpkPackGen(__u8 device,__u8 maskcnt,void *data);
00027 __u8 asciihead(__u8 head);
00028 void nwconvert(long data, char *asciiout, int size);
00029 char ctoa(__u8 nibble);
00030 __u8 hexatoc(char *asc);
00031 
00032 
00033 
00034 /*
00035 PcpkParsePacket
00036 -------------------------------------------------------------------------------
00037 fills a PcpkPacket
00038 if data is available
00039 
00040 parameters:
00041 *asciipacket - the received ascii string (the entire packet).
00042 *packet - pointer to a packet structure to be filled
00043 
00044 returns:
00045 success:
00046 0
00047 
00048 failure:
00049 NOPACKET - no valid packet header found.
00050 
00051 
00052 */
00053 int PcpkParsePacket(char *asciipacket,PcpkPacket *packet)
00054 {
00055 PcpkParseHeader(asciipacket,packet);
00056 
00057 PcpkParseData(asciipacket,packet);
00058 return 0;
00059 }
00060 
00061 
00062 /*
00063 PcpkParseHeader
00064 -------------------------------------------------------------------------------
00065 sets up the packet 
00066 This function is separated from the rest of the packet parsing 
00067 routines because it will be needed by the interrupt handler
00068 to know how long of a string to read before resetting it's pointer.
00069 For a full packet parsing function use PcpkParsePacket, above.
00070 
00071 parameters:
00072 *rxpacket - the received ascii string or byte array(the entire packet).
00073 *packet - pointer to a packet structure to be filled
00074 
00075 returns:
00076  success:
00077   the header in hexidecimal
00078   also, important parameters are stored in the PcpkPacket passed to it.
00079 
00080 */
00081 PcpkHeader PcpkParseHeader(char *rxpacket,PcpkPacket *packet)
00082 {
00083 PcpkHeader header;
00084 int error;
00085 
00086 #ifdef ASCIIPACKETS
00087 char tokenbuffer[4];
00088 char *asciiheader = &tokenbuffer[0];
00089 char packetbuffer[MAXPACKETSIZE];
00090 char *asciipacket = &packetbuffer[0];
00091 char cutbbuffer[5];/*a global buffer for the byte strsep function*/
00092  
00093 
00094 strcpy(asciipacket,rxpacket);
00095 /*copy packet in case the original was read only (a literal)*/
00096 //asciiheader = strsep(&asciipacket,DELIM);/*get header*/
00097 
00098 asciiheader = cutbyte(asciipacket, cutbbuffer);
00099 
00100 
00101 asciiheader[0] = (char)TRANS(asciiheader[0]);/*do header translation*/
00102 
00103 
00104 header = (PcpkHeader)strtoul(asciiheader,NULL,16); /*convert to hex*/
00105 
00106 #endif /*end ifdef asciipackets*/
00107 
00108 
00109 #ifdef BINPACKETS
00110 header = *rxpacket;
00111 #endif
00112 
00113 
00114 packet->type = PTYPE(header);
00115 
00116 if(packet->extended==TRUE)
00117   packet->type+=EXTNULCMD;
00118 
00119 packet->maskcnt = MASK(header);
00120 packet->format = FORMAT(packet->type);
00121 
00122 error = PcpkPacketAssign(packet);
00123 
00124 if(error<0)
00125 return error;
00126       
00127 return header;
00128 }
00129 
00130 
00131 
00132 
00133 /*
00134 PcpkParseData
00135 ------------------------------------------------------------------------------
00136 universal c packet parsing function for the pcpack.
00137 say that ten times fast.
00138 
00139 parameters:
00140  *rxpacket - the received ascii string or byte array(the entire packet).
00141  *packet - pointer to a packet structure to be filled
00142 
00143 returns:
00144  success:
00145   0
00146  failure:
00147  -1 
00148 
00149 notes:
00150    The ascii version of this  function could have been a lot short
00151 shorter and cleaner if I could have figured out a way
00152 to dynamically declare a variables type in straight C.
00153 Gcc seems to demand that all typedefs and declarations
00154 happen before anything else, hence I was limited.
00155 If anyone sees this code and has a suggestion, 
00156 I would be appreciate an e-mail, at ngustavson@emacinc.com. 
00157 
00158    The binary char implementation of this function is very simple,
00159 just a malloc and memcpy, the word version has to run through the whole
00160 "update the pointer" process. This way data is stored correctly.
00161 A straight memcpy would store the data in little endian format, and 
00162 everyone one would get confused and start calling me. 
00163 
00164 
00165 */
00166 int PcpkParseData(char *rxpacket,PcpkPacket *packet)
00167 {
00168 size_t packetsize;/*size of the data packet in bytes*/
00169 size_t datanum;
00170 char tokenbuffer[MAXPACKETSIZE];
00171 void *token = &tokenbuffer[0];
00172 //unsigned int asciicount;
00173 char *bytedata;
00174 __u16 *wrddata;/*some crazy OS's like linux think an int is 4 bytes*/
00175 //char wdata;
00176 char cutbbuffer[5];/*a global buffer for the byte strsep function*/
00177 
00178 #ifdef ASCIIPACKETS
00179 char packetbuffer[MAXPACKETSIZE];
00180 char *asciipacket = &packetbuffer[0];
00181 #endif
00182 
00183 
00184 
00185 packetsize = (packet->datasize)*(packet->datanum);
00186 //packet->data = vmalloc(packetsize);  
00187 /*virtual allocation fails during interrupt tasks
00188 so, ta hell wit it, I'll break down and use a fixed size array*/
00189 
00190 #ifdef BINPACKETS
00191 ++rxpacket; /*point past the header*/
00192 #endif
00193 
00194 
00195 #ifdef ASCIIPACKETS
00196 strcpy(asciipacket,rxpacket);
00197 /*copy packet in case the original was read only (a literal)*/
00198 #ifdef DELIM
00199 strsep(&asciipacket,DELIM);/* identify string and move past header */
00200 /* allocate memory for the data packet */
00201 #endif
00202 #endif
00203 
00204 bytedata = packet->data; /*2 different alignments for the 2 situations*/
00205 wrddata = (__u16 *)packet->data;
00206 
00207 switch(packet->datasize)
00208   {
00209   
00210   case 1:
00211     {
00212 #ifdef BINPACKETS /*a much simpler function, just a memcopy and a malloc*/
00213       memcpy(packet->data,rxpacket,packetsize);
00214       return 0;
00215 #endif 
00216 
00217       for(datanum=2;datanum<=packetsize*2;datanum+=2)
00218     {
00219 
00220       token = cutbyte(&asciipacket[datanum],cutbbuffer);
00221       /*2,4,6,8,10....*/
00222 #ifdef DELIM      
00223       token = strsep(&asciipacket,DELIM);
00224       /*delim no longer works*/
00225 #endif
00226 
00227      
00228 
00229      if(token == NULL)
00230        {
00231          packet->datanum = (datanum-2)/2;
00232          //realloc(packet->data, datanum);
00233          return PARSEERROR; 
00234        }
00235         *bytedata = (unsigned char)strtoul(token,NULL,16);;
00236     ++bytedata;
00237     }
00238       break;
00239     }
00240   case 2:
00241     {
00242       for(datanum=2;datanum<=packetsize*2;datanum+=4)
00243     {
00244      // for(asciicount=1;asciicount<=2;asciicount++)
00245        // {    
00246 #ifdef ASCIIPACKETS
00247           token = cutword(&asciipacket[datanum],cutbbuffer);
00248           /*2,4,6,8,10...*/
00249 #ifdef DELIM 
00250           token = strsep(&asciipacket,DELIM);
00251           /*delimeters no longer work here*/
00252 #endif        
00253           *wrddata = (unsigned short)strtoul(token,NULL,16);
00254 #endif
00255           
00256 #ifdef BINPACKETS
00257           if(*rxpacket==0)
00258         token = NULL;;
00259           wdata = *rxpacket;
00260           ++rxpacket;
00261 #endif
00262           
00263 
00264           
00265           
00266           if(token == NULL)
00267         {/* error, reallocate memory for incorrect packet size*/
00268           packet->datanum = (datanum-2)/4;
00269           //realloc(packet->data, datanum);
00270           return PARSEERROR; 
00271         }
00272           
00273 
00274 
00275      //}
00276         *wrddata = (unsigned short)strtoul(token,NULL,16);
00277       ++wrddata;/*point to the next data item*/
00278     }
00279       break;
00280     }
00281  
00282   }
00283 
00284 
00285 return 0;
00286 }
00287 
00288 
00289 
00290 /*  PcpkPacketAssign
00291 -----------------------------------------------------------------------------
00292  *
00293  *  assign parameters to packet structure based
00294  *  on written documentation in packet.h
00295  *  data is assigned based on PcpkPacket.format, so it must be already set.
00296  *  a switch statement was so that if other parameters need to
00297  *  be added later, changes would be easy.
00298  */
00299 int PcpkPacketAssign(PcpkPacket *packet)
00300 {
00301 
00302 packet->extended = FALSE; //by default extended packets are off
00303 
00304 switch(packet->format)
00305   {
00306   case INVLTYP:
00307     return NOPACKET;
00308     
00309   case MRKTYP0:
00310     {
00311       packet->datasize = 1;
00312       packet->datanum = Pcpkonescount(packet->maskcnt);
00313       packet->mult = 0;
00314       break;
00315     }
00316 
00317   case MRKTYP1:
00318     {
00319       packet->datasize = 2;
00320       packet->datanum = Pcpkonescount(packet->maskcnt);
00321       packet->mult = 0;
00322       break;
00323     }
00324 
00325   case MRKTYP2:
00326     {
00327       packet->datasize = 1;
00328       packet->maskcnt = packet->maskcnt|(packet->mult<<4);
00329       packet->datanum = packet->maskcnt;
00330       packet->mult = 0;
00331       break;
00332     }
00333 
00334   case MRKTYP3:
00335     {
00336       packet->datasize = 2;
00337       packet->datanum = 1;
00338       packet->mult = 0;
00339       break;
00340     }
00341 
00342  case MRKTYP4:
00343     {
00344       packet->datasize = 0;
00345       packet->datanum = 0;
00346       packet->mult = 0;     
00347       break;
00348     }
00349 
00350   case MRKTYP5:
00351     {
00352       packet->extended = TRUE;
00353       packet->datanum = 0;
00354       packet->mult = 0;     
00355       break;
00356     }
00357 
00358   case MRKTYP6:
00359     {
00360      packet->extended = TRUE;
00361      packet->datanum = 0;
00362      packet->mult = packet->maskcnt;
00363      break;  
00364     }
00365 
00366   default:
00367     {
00368      packet->datanum = 0;
00369      packet->mult = 0;
00370     }
00371 
00372 
00373   }/*end switch(packet->type)*/
00374 
00375 
00376 return 0;
00377 }
00378 
00379 
00380 
00381 /*Pcpkonescount
00382 -------------------------------------------------------------------------------
00383 counts the ones in a 4 bit mask
00384 */
00385 unsigned int Pcpkonescount(unsigned char mask)
00386 {
00387 unsigned int count;
00388 unsigned int ones = 0;
00389 
00390 for(count=0;count<=3;count++)
00391   {
00392   ones += mask&0x01;
00393   mask >>= 1;
00394   }
00395 
00396 return  ones;
00397 }
00398 
00399 
00400 
00401 /*PcpkPacketDestroy
00402 ------------------------------------------------------------------------------
00403 destroys a previously allocated packet
00404 and frees the memory used.
00405 */
00406 int PcpkPacketDestroy (PcpkPacket *packet)
00407 {
00408   /*no longer needed*/
00409 //vfree(packet->data);
00410 
00411 return 0;
00412 }
00413 
00414 
00415 /* a strsep type function that separates a string into tokens, ala strsep,
00416 but instead of basing it on delimiters, does bytes
00417 
00418 returns the token, doesn't modify the original string
00419 
00420 this used to use a global variable so wasn't thread safe, but this has
00421 been changed for the 37e12. The buffer is now passed into the function
00422 from the calling function, not as pretty, but much safer.
00423 */
00424 char *cutbyte(char *stringin, __u8 *cutbbuffer)
00425 {
00426 strncpy(&cutbbuffer[0],stringin,2);/*copy byte to the global buffer*/
00427 cutbbuffer[2] = '\0';/*end the string*/
00428 return &cutbbuffer[0];
00429 }
00430 
00431 
00432 unsigned short *cutword(char *stringin, __u8 *cutbbuffer)
00433 {
00434 strncpy(&cutbbuffer[0],stringin,4);/*copy word to the global buffer*/
00435 cutbbuffer[4] = '\0';/*end the string*/
00436 return (unsigned short *)&cutbbuffer[0];
00437 }
00438 
00439 
00440 
00441 
00442 
00443 /*
00444 PcpkPackGen
00445 --------------------------------------------------------------
00446 A general packet creating function
00447 */
00448 char *PcpkPackGen(__u8 device,__u8 maskcnt,void *data)
00449 {
00450 
00451 __u8 type = hdrTbl[device];
00452 char *packet;
00453 __u16 datanum;
00454 __u8 datasiz = 2;/*2 ascii chars for 1 char default*/
00455 char *databuff;
00456 __u16 offset;
00457 __u8 bitmask = 8;
00458 __u16 *__u16ptr = data;
00459 char *charptr = data;
00460 int count=0;
00461 //__u8 maskhigh = maskcnt;
00462 __u8 mask = maskcnt;
00463 
00464 maskcnt&=0x0F;
00465 /*
00466 if(maskcnt>0x0F)
00467 {
00468 GENDEBUG("invalid mask\n");
00469 return NULL;
00470 }
00471 */
00472 if(device>=LPHEADERS)
00473 {
00474 switch(type)
00475 {
00476 case MRKTYP2:
00477     /*data is an array of bytes*/
00478     datanum = mask;
00479     datasiz = 2;    
00480 
00481     if(NULL==(databuff = malloc(datanum*datasiz + 1)))
00482     return FAILURE;
00483 
00484 
00485         for(offset=0;offset<datanum;offset++)   
00486     nwconvert((int)charptr[offset],&databuff[offset*datasiz],datasiz);
00487   
00488     //sprintf(&databuff[offset*datasiz],"%X",charptr[offset]);
00489     
00490     databuff[offset*datasiz]=0;
00491 
00492     break;
00493 
00494 }
00495 
00496 }
00497 else
00498 {
00499 switch(type)
00500 {
00501   case INVLTYP:
00502   GENDEBUG("invalid type\n");
00503   return NULL;
00504 
00505 
00506   
00507   case MRKTYP0:
00508     /*data is an array of masked 4 bytes*/
00509     datasiz=2;
00510     datanum = Pcpkonescount(maskcnt);
00511     if(NULL==(databuff = malloc(datanum*datasiz + 1)))
00512     return FAILURE;
00513 
00514     for(offset=0;offset<4;offset++)
00515     {
00516     if(bitmask&maskcnt)
00517       {
00518        nwconvert((__u16)charptr[offset],&databuff[count*datasiz],datasiz);
00519        count++;
00520       }
00521     bitmask>>=1;
00522     }
00523     databuff[count*datasiz]=0;
00524     break;
00525  
00526 
00527 
00528 
00529  
00530   
00531   case MRKTYP1:/*change data size*/
00532     /*data is an array of masked 4 __u16s*/
00533     datasiz = 4;
00534         
00535     datanum = Pcpkonescount(maskcnt);
00536 
00537     if(NULL==(databuff = malloc(datanum*datasiz + 1)))
00538     return FAILURE;
00539 
00540     for(offset=0;offset<4;offset++)
00541     {
00542     if(bitmask&maskcnt)
00543       {
00544        //sprintf(&databuff[count*datasiz],"%X",__u16ptr[offset]);
00545        nwconvert(__u16ptr[offset],&databuff[count*datasiz],datasiz);
00546        count++;
00547       }     
00548      
00549 
00550     bitmask>>=1;
00551     }
00552     databuff[count*datasiz]=0;
00553     break;
00554   
00555 
00556 
00557 
00558   case MRKTYP2:
00559     /*data is an array of bytes*/
00560     datanum = maskcnt;
00561     datasiz = 2;    
00562 
00563     if(NULL==(databuff = malloc(datanum*datasiz + 1)))
00564     return FAILURE;
00565 
00566 
00567         for(offset=0;offset<datanum;offset++)   
00568     nwconvert((int)charptr[offset],&databuff[offset*datasiz],datasiz);
00569   
00570     //sprintf(&databuff[offset*datasiz],"%X",charptr[offset]);
00571     
00572     databuff[offset*datasiz]=0;
00573 
00574     break;
00575 
00576 
00577 case MRKTYP3:
00578     /*data is a single word*/
00579     datanum = 1;
00580     datasiz = 4;
00581 
00582     if(NULL==(databuff = malloc(datanum*datasiz + 1)))
00583     return FAILURE;
00584 
00585 
00586         nwconvert(__u16ptr[0],&databuff[0],datasiz);
00587     
00588     databuff[datasiz]=0;
00589 
00590     break;
00591 
00592 
00593 case MRKTYP4:
00594     /*data a header only*/
00595     if(NULL==(databuff = malloc(1)))
00596     return FAILURE;
00597 
00598     *databuff = 0;
00599     break;
00600 
00601 
00602 
00603 }
00604 }
00605 
00606 if(device>=EXTNULCMD)//extended packet
00607   packet = malloc((datanum*datasiz)+(HEADERSIZE*2)+1);
00608 else
00609   packet = malloc((datanum*datasiz)+HEADERSIZE+1);
00610 
00611 
00612 if(packet==NULL)
00613 {
00614 GENDEBUG("unable to allocate memory for packet\n");
00615 return FAILURE;
00616 }
00617 /*generate the header*/
00618 packet[DELIMITER] = (device + 0x61);
00619 //sprintf(&packet[MASKNIB],"%X",maskcnt);
00620 nwconvert(maskcnt,&packet[MASKNIB],1);
00621 //sprintf keeps going insane
00622 
00623 
00624 if(device>=EXTNULCMD)//extended packet
00625   {
00626   packet[DELIMITER] = (EXTCMD + 0x61);
00627   packet[EXT_DELIMITER] = device - EXTNULCMD + 'A';
00628   nwconvert(maskcnt,&packet[EXT_MASKNIB],1);
00629   nwconvert((maskcnt>>4),&packet[MASKNIB],1);//redo original
00630   packet[EXT_MASKNIB+1]=0;
00631   }
00632 else
00633   packet[MASKNIB+1]=0;
00634 
00635 if(device>=LPHEADERS)
00636 packet[DELIMITER] = (LONG_EXT + 0x61);
00637 
00638 
00639 
00640 /*cat the data*/
00641 
00642 strcat(packet,databuff);
00643 
00644 free(databuff);
00645 /*destroy the temporary data storage*/
00646 
00647 return packet;
00648 }
00649 
00650 
00651 __u8 asciihead(__u8 head)
00652 {
00653 if(head>TRANSFLIP)
00654 return(head - 10);
00655 
00656 return(head - 0x31);
00657 }
00658 
00659 
00660 
00661 void nwconvert(long data, char *asciiout, int size)
00662 {
00663 int i;
00664 
00665     for(i=(size-1);i>=0;i--)
00666      {
00667       asciiout[i] = ctoa(((__u8)data&0x0F));
00668       data>>=4;
00669      }
00670 } 
00671 
00672 
00673 
00674 char ctoa(__u8 nibble)
00675 {
00676 if (nibble>9)
00677     return(nibble + 55);
00678 else
00679     return(nibble + 48);
00680 }
00681 
00682 __u8 hexatoc(char *asc)
00683 {
00684 __u8 charback = 0;
00685 int charnum;
00686 __u8 temp;
00687 int expon;
00688 
00689 for(charnum=0;charnum<=1;charnum++)
00690 {
00691 if(asc[charnum]>=97)
00692     temp = asc[charnum] - 87;
00693 else    
00694 if(asc[charnum]>=65)
00695     temp = asc[charnum] - 55;
00696 else
00697     temp = asc[charnum] - 48;
00698 
00699 
00700 //expon = 16^(1-charnum);
00701 expon = 1<<(4*(1-charnum));
00702 temp*=expon;
00703 charback+= temp;
00704 }
00705 
00706 return charback;
00707 }
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 

Generated on Mon Dec 29 09:25:43 2003 for PCM-37e12 by doxygen1.2.15