/************************** Functions Definitions **********************/ uint8_t KeyPad_getPressedKey(void){ uint8_t col,row; while(1) { for(col=0;col<N_col;col++) /* loop for columns */ { /* * each time only one of the column pins will be output and * the rest will be input pins include the row pins */ KEYPAD_PORT_DIR = (0b11110000); /* * clear the output pin column in this trace and enable the internal * pull up resistors for the rows pins */ KEYPAD_PORT_OUT = (~(0b00010000<<col)); for(row=0;row<N_row;row++) /* loop for rows */ { if(BIT_IS_CLEAR(KEYPAD_PORT_IN,row)) /* if the switch is press in this row */ { while(BIT_IS_CLEAR(KEYPAD_PORT_IN,row));/* will active when you release the button*/ #if (N_col == 3) return KeyPad_4x3_adjustKeyNumber((row*N_col)+col+1); #elif (N_col == 4) return KeyPad_4x4_adjustKeyNumber((row*N_col)+col+1); #endif } } } } }
/* ----------------------------------------------------------------------------------------------------- [Function Name] : DIO_readPin [Description] : This function is responsible for reading the input value of the selected port and pin [Args] : [in] const DioConfig * a_s_STATE_Ptr : This argument is the address of an object of the struct DioConfig containing all information about the targeted registers of the hardware The received struct will contain : 1. The PORT Which the hardware belongs to 'A' 'B' 'C' or 'D' 2. The number of the pin in the PORT '0 -> 7' 3. The direction of pin 'INPUT' or 'OUTPUT' 4. The value of the pin 'Logic_High' or 'Logic_Low' [out] uint8 output : This variable will store the value of the targeted pin [Returns] : output is the value of the targeted pin ( Logic High or Logic Low ) ----------------------------------------------------------------------------------------------------- */ uint8 DIO_readPin( const DioConfig * a_s_STATE_Ptr ) { uint8 * pin_Ptr; uint8 output; /* point to the required PORT Register */ switch( a_s_STATE_Ptr->port ) { case 'A': pin_Ptr = &PINA; break; case 'B': pin_Ptr = &PINB; break; case 'C': pin_Ptr = &PINC; break; case 'D': pin_Ptr = &PIND; break; } /* check if the corresponding bit is set in the PIN register */ if( BIT_IS_SET( *pin_Ptr , a_s_STATE_Ptr->pinNum ) ) { output = LOGIC_HIGH; } /* check if the corresponding bit is clear in the PIN register */ else if( BIT_IS_CLEAR( *pin_Ptr , a_s_STATE_Ptr->pinNum ) ) { output = LOGIC_LOW; } return output; }
uint8 DIO_Read_Pin(const DIO_Config * s_State) { volatile uint8 * PIN_Ptr; uint8 output; /* point to the required PIN Register */ switch(s_State->port) { case 'A': PIN_Ptr = &PINA; break; case 'B': PIN_Ptr = &PINB; break; case 'C': PIN_Ptr = &PINC; break; case 'D': PIN_Ptr = &PIND; break; } if(BIT_IS_SET(*PIN_Ptr,s_State->pin_num)) //check if the corresponding bit is set in the PIN register { output = LOGIC_HIGH; } else if(BIT_IS_CLEAR(*PIN_Ptr,s_State->pin_num)) //check if the corresponding bit is clear in the PIN register { output = LOGIC_LOW; } return output; }
uint8 DIO_readPin(const DioConfig * a_STATE_Ptr) { volatile uint8 * PORT_Ptr; uint8 state; /* point to the required PIN Register */ switch( a_STATE_Ptr -> port ) { case 'A': PORT_Ptr = &PORTA; break; case 'B': PORT_Ptr = &PORTB; break; case 'C': PORT_Ptr = &PORTC; break; case 'D': PORT_Ptr = &PORTD; break; } if (BIT_IS_SET(*PORT_Ptr, a_STATE_Ptr -> pinNum)) { state = LOGIC_HIGH; } else if(BIT_IS_CLEAR(*PORT_Ptr,a_STATE_Ptr -> pinNum)) { state = LOGIC_LOW; } return state; }
/* EEPROM read Byte from EEPROM at specific address */ uint8_t EEPROM_read(uint16_t uiAddress) { /* Wait for completion of previous write */ while(!BIT_IS_CLEAR(EECR,EEWE)); ; /* Set up address register */ EEAR = uiAddress; /* Start eeprom read by writing EERE */ SET_BIT(EECR,EERE); /* Return data from data register */ return EEDR; }
/* EEPROM write Byte into EEPROM at specific address */ void EEPROM_write(uint16_t uiAddress, uint8_t ucData) { /* Wait for completion of previous write */ while(!BIT_IS_CLEAR(EECR,EEWE)); ; /* Set up address and data registers */ EEAR = uiAddress; EEDR = ucData; /* Write logical one to EEMWE */ SET_BIT(EECR,EEMWE); /* Start eeprom write by setting EEWE */ SET_BIT(EECR,EEWE); }
int main(void) { DDRD &= ~(1 << PD2); // clear DDRD bit 2, sets PD2 (pin 4) for input PORTD |= (1 << PD2); // set PORTD bit 2, sets PD2 (pin 4) internal pull-up resistor DDRC |= (1 << PC5); // set DDRC bit 5, sets PC5 (pin 28) for output while (1) { // begin infinite loop if(BIT_IS_CLEAR(PIND, PD2)) { // check if PIND bit 2 is clear, which indicates switch is pressed (logic low) PORTC |= (1 << PC5); // set PORTC bit 5 to set PC5 (pin 28) high } else if(BIT_IS_SET(PIND, PD2)) { // check if PIND bit 2 is set, which indicates switch is not pressed (logic low) PORTC &= ~(1 << PC5); // clear PORTC, bit 5 to set PC5 (pin 28) low } else { // ideally should never get here, but may occasionally due to timing } } return(0); // should never get here, this is to prevent a compiler warning }
static int dissect_dvb_s2_bb(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo) { proto_item *ti, *tf; proto_tree *dvb_s2_bb_tree, *dvb_s2_bb_matype1_tree; guint8 input8; guint16 input16, bb_data_len = 0; int sub_dissected = 0, flag_is_ms = 0, new_off = 0; col_append_str(pinfo->cinfo, COL_PROTOCOL, "BB "); col_append_str(pinfo->cinfo, COL_INFO, "Baseband "); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_dvb_s2_bb, tvb, cur_off, DVB_S2_BB_HEADER_LEN, ENC_NA); dvb_s2_bb_tree = proto_item_add_subtree(ti, ett_dvb_s2_bb); input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1); new_off += 1; if (BIT_IS_CLEAR(input8, DVB_S2_BB_MIS_POS)) flag_is_ms = 1; tf = proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_matype1, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, input8); dvb_s2_bb_matype1_tree = proto_item_add_subtree(tf, ett_dvb_s2_bb_matype1); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_gs, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_mis, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_acm, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_issyi, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_npd, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_bb_matype1_tree, hf_dvb_s2_bb_matype1_ro, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, 1, ENC_BIG_ENDIAN); input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2); new_off += 1; if (flag_is_ms) { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "Input Stream Identifier (ISI): %d", input8); } else { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "reserved"); } input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_UPL); new_off += 2; proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_upl, tvb, cur_off + DVB_S2_BB_OFFS_UPL, 2, input16, "User Packet Length: %d bits (%d bytes)", (guint16) input16, (guint16) input16 / 8); bb_data_len = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_DFL); bb_data_len /= 8; new_off += 2; proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_dfl, tvb, cur_off + DVB_S2_BB_OFFS_DFL, 2, input16, "%d bits (%d bytes)", input16, input16 / 8); new_off += 1; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_sync, tvb, cur_off + DVB_S2_BB_OFFS_SYNC, 1, ENC_BIG_ENDIAN); new_off += 2; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_syncd, tvb, cur_off + DVB_S2_BB_OFFS_SYNCD, 2, ENC_BIG_ENDIAN); input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_CRC); new_off += 1; if (check_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, cur_off, input8)) { proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_crc, tvb, cur_off + DVB_S2_BB_OFFS_CRC, 1, 1, "Checksum: correct (0x%2.2x)", input8); } else { proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_crc, tvb, cur_off + DVB_S2_BB_OFFS_CRC, 1, -1, "Checksum: incorrect! (0x%2.2x)", input8); } while (bb_data_len) { /* start DVB-GSE dissector */ sub_dissected = dissect_dvb_s2_gse(tvb, cur_off + new_off, tree, pinfo); new_off += sub_dissected; if ((sub_dissected <= bb_data_len) && (sub_dissected >= DVB_S2_GSE_MINSIZE)) { bb_data_len -= sub_dissected; if (bb_data_len < DVB_S2_GSE_MINSIZE) bb_data_len = 0; } else bb_data_len = 0; } return new_off; }
/* *** Code to actually dissect the packets *** */ static int dissect_dvb_s2_gse(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo) { int new_off = 0; int frag_len; guint16 gse_hdr, data_len, gse_proto = 0; proto_item *ti, *tf; proto_tree *dvb_s2_gse_tree, *dvb_s2_gse_hdr_tree; tvbuff_t *next_tvb; col_append_str(pinfo->cinfo, COL_INFO, "GSE"); /* get header and determine length */ gse_hdr = tvb_get_ntohs(tvb, cur_off + DVB_S2_GSE_OFFS_HDR); new_off += 2; frag_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK)+2; ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, cur_off, frag_len, ENC_NA); dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse); tf = proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_hdr, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, gse_hdr); dvb_s2_gse_hdr_tree = proto_item_add_subtree(tf, ett_dvb_s2_gse_hdr); proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_start, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_stop, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_labeltype, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_length, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN); if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { col_append_str(pinfo->cinfo, COL_INFO, " "); return new_off; } else { if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); new_off += 2; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) { gse_proto = tvb_get_ntohs(tvb, cur_off + new_off); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); new_off += 2; if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 6 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "6 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, tvb, cur_off + new_off, 6, ENC_NA); new_off += 6; } else if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 3 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "3 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, tvb, cur_off + new_off, 3, ENC_NA); new_off += 3; } else { /* 0 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "0 "); } if (gse_proto < 0x0600 && gse_proto >= 0x100) { /* Only display optional extension headers */ /* TODO: needs to be tested */ /* TODO: implementation needs to be checked (len of ext-header??) */ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } } else { /* correct cinfo */ col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); } next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off); if (dvb_s2_full_dissection) { switch (gse_proto) { case ETHERTYPE_IP: new_off += call_dissector(ip_handle, next_tvb, pinfo, tree); break; case ETHERTYPE_IPv6: new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree); break; default: if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; break; } } else { if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; } /* add crc32 if last fragment */ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_NA); new_off += DVB_S2_GSE_CRC32_LEN; } } return new_off; }
int main(int argc, char *argv[]) { int opt = 0; char cmd[128] = {'\0'}; char result[16] = {'\0'}; unsigned int value = 0; unsigned int parm = 0; unsigned short rate = 0; unsigned char duplex = 0; unsigned char link = 0; system("echo 0 > /proc/sys/kernel/printk"); if((opt = getopt(argc,argv,"rlhs:d:")) != -1) { /*get the value of the reg*/ if(!PopenFile("/usr/sbin/ethreg -p 0x00 0x00 | awk -F\"= 0x\" '{print$2}'", result, sizeof(result))){ printf("/usr/sbin/ethreg -p 0x00 0x00 | awk -F\"= 0x\" '{print$2}' is error\n"); } /*form the value*/ sscanf(result , "%x", &value); switch (opt) { case 'h': iw_usage(); break; case 'r': // reset phy chip match to the 15th bit /*check parm*/ if(argc > 2){ goto FAIL; } SET_BIT(value,15); break; case 's': //set rate 00:10M/s, 01:100M/s, 10:1000M/s, 11:negotiation-0 /*check parm*/ if(argc > 3){ goto FAIL; } parm = atoi(argv[argc - 1]); if( 0 != parm && 10 != parm && 100 != parm && 1000 != parm ){ goto FAIL; } /* enable auto-negotiation process match to the 8th bit 00:10M/s, 01:100M/s, 10:1000M/s high bit match to the 6th bit, low bit match to the 13th bit */ if( 0 == parm){ SET_BIT(value, 12); CLEAR_BIT(value, 13); CLEAR_BIT(value, 6); }else if( 10 == parm ){ CLEAR_BIT(value, 12); CLEAR_BIT(value, 13); CLEAR_BIT(value, 6); }else if( 100 == parm ){ CLEAR_BIT(value, 12); SET_BIT(value, 13); CLEAR_BIT(value, 6); }else if( 1000 == parm ){ CLEAR_BIT(value, 12); CLEAR_BIT(value, 13); SET_BIT(value, 6); } break; case 'd': /*set the duplex 0:half, 1:full match to the 8th bit*/ /*check parm*/ if(argc > 3){ goto FAIL; } parm = atoi(argv[argc - 1]); if(0 != parm && 1 != parm){ goto FAIL; } if(parm){ SET_BIT(value, 8); }else{ CLEAR_BIT(value, 8); } break; case 'l': if(argc > 2){ goto FAIL; } /*read the status of the reg*/ if(!PopenFile("/usr/sbin/ethreg -p 0x00 0x11 | awk -F\"= 0x\" '{print$2}'", result, sizeof(result))){ printf("/usr/sbin/ethreg -p 0x00 0x11 | awk -F\"= 0x\" '{print$2}' is error\n"); } /*form the value*/ sscanf(result , "%x", &value); /*get the link status*/ if( BIT_IS_SET(value, 10) ){ printf("the link status is up\n"); }else{ printf("the link status is down\n"); } /*get the duplex*/ if( BIT_IS_SET(value, 13) ){ printf("the work mode is full-duplex\n"); }else{ printf("the work mode is half-duplex\n"); } /*get the rate 00:10M/s, 01:100M/s, 10:1000M/s high bit match to the 15th bit, low bit match to the 14th bit */ if(BIT_IS_CLEAR(value, 15) && BIT_IS_CLEAR(value, 14)){ //00:10M/s printf("the rate is 10M/s\n"); }else if(BIT_IS_CLEAR(value, 15) && BIT_IS_SET(value, 14)){ //01:100M/s printf("the rate is 100M/s\n"); }else if(BIT_IS_SET(value, 15) && BIT_IS_CLEAR(value, 14)){ //10:1000M/s printf("the rate is 1000M/s\n"); }else{ printf("the rate is error\n"); } break; default: goto FAIL; } /*set the value of the reg*/ if( 's' == opt || 'd' == opt || 'r' == opt){ sprintf(cmd, "/usr/sbin/ethreg -p 0x00 0x00=0x%x >> /dev/null 2>&1", value); system(cmd); } }else{ goto FAIL; } system("echo 7 > /proc/sys/kernel/printk"); return 0; FAIL: system("echo 7 > /proc/sys/kernel/printk"); iw_usage(); return -1; }
static int dissect_dvb_s2_bb(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo) { proto_item *ti; proto_tree *dvb_s2_bb_tree; guint8 input8, matype1; guint16 input16, bb_data_len = 0, user_packet_length; int sub_dissected = 0, flag_is_ms = 0, new_off = 0; static const int * bb_header_bitfields[] = { &hf_dvb_s2_bb_matype1_gs, &hf_dvb_s2_bb_matype1_mis, &hf_dvb_s2_bb_matype1_acm, &hf_dvb_s2_bb_matype1_issyi, &hf_dvb_s2_bb_matype1_npd, &hf_dvb_s2_bb_matype1_ro, NULL }; col_append_str(pinfo->cinfo, COL_PROTOCOL, "BB "); col_append_str(pinfo->cinfo, COL_INFO, "Baseband "); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_dvb_s2_bb, tvb, cur_off, DVB_S2_BB_HEADER_LEN, ENC_NA); dvb_s2_bb_tree = proto_item_add_subtree(ti, ett_dvb_s2_bb); matype1 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1); new_off += 1; if (BIT_IS_CLEAR(matype1, DVB_S2_BB_MIS_POS)) flag_is_ms = 1; proto_tree_add_bitmask_with_flags(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, hf_dvb_s2_bb_matype1, ett_dvb_s2_bb_matype1, bb_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_FLAGS); input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2); new_off += 1; if (flag_is_ms) { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "Input Stream Identifier (ISI): %d", input8); } else { proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "reserved"); } user_packet_length = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_UPL); new_off += 2; proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_upl, tvb, cur_off + DVB_S2_BB_OFFS_UPL, 2, input16, "User Packet Length: %d bits (%d bytes)", (guint16) input16, (guint16) input16 / 8); bb_data_len = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_DFL); bb_data_len /= 8; new_off += 2; proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_dfl, tvb, cur_off + DVB_S2_BB_OFFS_DFL, 2, input16, "%d bits (%d bytes)", input16, input16 / 8); new_off += 1; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_sync, tvb, cur_off + DVB_S2_BB_OFFS_SYNC, 1, ENC_BIG_ENDIAN); new_off += 2; proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_syncd, tvb, cur_off + DVB_S2_BB_OFFS_SYNCD, 2, ENC_BIG_ENDIAN); new_off += 1; proto_tree_add_checksum(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_CRC, hf_dvb_s2_bb_crc, hf_dvb_s2_bb_crc_status, &ei_dvb_s2_bb_crc, pinfo, compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, cur_off), ENC_NA, PROTO_CHECKSUM_VERIFY); switch (matype1 & DVB_S2_BB_TSGS_MASK) { case DVB_S2_BB_TSGS_GENERIC_CONTINUOUS: /* Check GSE constraints on the BB header per 9.2.1 of ETSI TS 102 771 */ if (BIT_IS_SET(matype1, DVB_S2_BB_ISSYI_POS)) { expert_add_info(pinfo, ti, &ei_dvb_s2_bb_issy_invalid); } if (BIT_IS_SET(matype1, DVB_S2_BB_NPD_POS)) { expert_add_info(pinfo, ti, &ei_dvb_s2_bb_npd_invalid); } if (user_packet_length != 0x0000) { expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_upl_invalid, "UPL is 0x%04x. It must be 0x0000 for GSE packets.", user_packet_length); } while (bb_data_len) { /* start DVB-GSE dissector */ sub_dissected = dissect_dvb_s2_gse(tvb, cur_off + new_off, tree, pinfo, bb_data_len); new_off += sub_dissected; if ((sub_dissected <= bb_data_len) && (sub_dissected >= DVB_S2_GSE_MINSIZE)) { bb_data_len -= sub_dissected; if (bb_data_len < DVB_S2_GSE_MINSIZE) bb_data_len = 0; } else { bb_data_len = 0; } } break; case DVB_S2_BB_TSGS_GENERIC_PACKETIZED: proto_tree_add_item(tree, hf_dvb_s2_bb_packetized, tvb, cur_off + new_off, bb_data_len, ENC_NA); new_off += bb_data_len; break; case DVB_S2_BB_TSGS_TRANSPORT_STREAM: proto_tree_add_item(tree, hf_dvb_s2_bb_transport, tvb, cur_off + new_off, bb_data_len, ENC_NA); new_off += bb_data_len; break; default: proto_tree_add_item(tree, hf_dvb_s2_bb_reserved, tvb, cur_off + new_off,bb_data_len, ENC_NA); new_off += bb_data_len; expert_add_info(pinfo, ti, &ei_dvb_s2_bb_reserved); break; } return new_off; }
/* *** Code to actually dissect the packets *** */ static int dissect_dvb_s2_gse(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo, int bytes_available) { int new_off = 0; int frag_len; guint16 gse_hdr, data_len, padding_len, gse_proto = 0; proto_item *ti; proto_tree *dvb_s2_gse_tree; tvbuff_t *next_tvb; static const int * gse_header_bitfields[] = { &hf_dvb_s2_gse_hdr_start, &hf_dvb_s2_gse_hdr_stop, &hf_dvb_s2_gse_hdr_labeltype, &hf_dvb_s2_gse_hdr_length, NULL }; col_append_str(pinfo->cinfo, COL_INFO, " GSE"); /* get the GSE header */ gse_hdr = tvb_get_ntohs(tvb, cur_off + DVB_S2_GSE_OFFS_HDR); /* check if this is just padding, which takes up the rest of the frame */ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { padding_len = bytes_available; proto_tree_add_uint_format(tree, hf_dvb_s2_gse_padding, tvb, cur_off + new_off, padding_len, padding_len, "DVB-S2 GSE Padding, Length: %d", padding_len); col_append_str(pinfo->cinfo, COL_INFO, " pad"); new_off += padding_len; return new_off; } else { /* Not padding, parse as a GSE Header */ new_off += 2; frag_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK)+2; ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, cur_off, frag_len, ENC_NA); dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse); proto_tree_add_bitmask_with_flags(dvb_s2_gse_tree, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, hf_dvb_s2_gse_hdr, ett_dvb_s2_gse_hdr, gse_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_TFS); if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); new_off += 2; } if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) { gse_proto = tvb_get_ntohs(tvb, cur_off + new_off); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN); new_off += 2; if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 6 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "6 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, tvb, cur_off + new_off, 6, ENC_NA); new_off += 6; } else if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) { /* 3 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "3 "); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, tvb, cur_off + new_off, 3, ENC_BIG_ENDIAN); new_off += 3; } else { /* 0 byte label */ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) col_append_str(pinfo->cinfo, COL_INFO, "0 "); } if (gse_proto < 0x0600 && gse_proto >= 0x100) { /* Only display optional extension headers */ /* TODO: needs to be tested */ /* TODO: implementation needs to be checked (len of ext-header??) */ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN); new_off += 1; } } else { /* correct cinfo */ col_append_str(pinfo->cinfo, COL_INFO, "(frag) "); } next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off); if (dvb_s2_full_dissection) { switch (gse_proto) { case ETHERTYPE_IP: new_off += call_dissector(ip_handle, next_tvb, pinfo, tree); break; case ETHERTYPE_IPv6: new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree); break; default: if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; break; } } else { if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN; } else data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE); proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA); new_off += data_len; } /* add crc32 if last fragment */ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) { proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_BIG_ENDIAN); new_off += DVB_S2_GSE_CRC32_LEN; } } return new_off; }