示例#1
0
// Setup reader to card connection
//
// The setup consists of a three way handshake:
//  - Receive initialisation vector 7 bits
//  - Transmit card type 6 bits
//  - Receive Acknowledge 6 bits
static int32_t setup_phase(legic_card_select_t *p_card) {
  uint8_t len = 0;

  // init coordination timestamp
  last_frame_end = GetCountSspClk();

  // reset prng
  legic_prng_init(0);

  // wait for iv
  int32_t iv = rx_frame(&len);
  if((len != 7) || (iv < 0)) {
    return -1;
  }

  // configure prng
  legic_prng_init(iv);

  // reply with card type
  switch(p_card->tagtype) {
    case 0:
      tx_frame(0x0D, 6);
      break;
    case 1:
      tx_frame(0x1D, 6);
      break;
    case 2:
      tx_frame(0x3D, 6);
      break;
  }

  // wait for ack
  int32_t ack = rx_frame(&len);
  if((len != 6) || (ack < 0)) {
    return -1;
  }

  // validate data
  switch(p_card->tagtype) {
    case 0:
      if(ack != 0x19) return -1;
      break;
    case 1:
      if(ack != 0x39) return -1;
      break;
    case 2:
      if(ack != 0x39) return -1;
      break;
  }

  // During rx the prng is clocked using the variable reader period.
  // Since rx_frame detects end of frame by detecting a code violation,
  // the prng is off by one bit period after each rx phase. Hence, tx
  // code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
  // This is not possible for back to back rx, so this quirk reduces
  // the gap by one period.
  last_frame_end += TAG_BIT_PERIOD;

  return 0;
}
示例#2
0
static int32_t connected_phase(legic_card_select_t *p_card) {
  uint8_t len = 0;

  // wait for command
  int32_t cmd = rx_frame(&len);
  if(cmd < 0) {
    return -1;
  }

  // check if command is LEGIC_READ
  if(len == p_card->cmdsize) {
    // prepare data
    uint8_t byte = legic_mem[cmd >> 1];
    uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);

    // transmit data
    tx_frame((crc << 8) | byte, 12);

    return 0;
  }
示例#3
0
//Handler for OI, moved from control.
void oi_system()
{
	movement_data_t movement_data;
	rotation_data_t rotation_data;
	
	enum {
		oi_command_init = 0,
		oi_command_move = 1,
		oi_command_rotate = 2,
		oi_command_play_song = 3,
		oi_command_dump = 4,
		oi_command_end_sequence = 5
	} oi_command = usart_rx();

	txq_enqueue(oi_command);

	switch (oi_command) {

		case oi_command_init:
			oi_init(&(control.oi_state));
			break;

		case oi_command_move:
	
			if(rx_frame()) {
				r_error(error_frame,"Move should not have multiple frames.");
			}

			struct {
				uint16_t speed;
				uint16_t dist;
				bool stream;
			} *move_data = (void *) &control.data;
			
			struct {
				uint16_t dist;
				uint8_t flag;
			} *response_move = (void *) &control.data;

			#warning "Stream functionality to be implemented later."
			//Stream returns the distance traveled
			//lcd_puts  ("In OI subsystem"); //debug
			movement_data = move_dist(&(control.oi_state), move_data->dist, move_data->speed);
			
			response_move->dist = movement_data.travelled;
			response_move->flag = movement_data.flag;
			
			if (movement_data.flag != 0) {
				movement_data = move_dist(&(control.oi_state), -20, move_data->speed);
				response_move->dist += movement_data.travelled;
			}

			control.data_len = 3;
			tx_frame(false);
			break;

		case oi_command_rotate:

			if (rx_frame()) {
				r_error(error_bad_message, "Rotate should only have one data frame.");
			}

			int16_t *angle = &(control.data[0]); // TODO: test if this is the right number of bytes

			if (control.data_len != 2/*sizeof(*angle)*/) { // TODO: hardcoding to debug
				r_error(error_bad_message, "Received too much data with rotate "
																	   "message.");
			}

			struct {
				uint16_t rotation;
			} *response_rotation = (void *) &control.data;

			rotation_data = turn(&(control.oi_state), *angle);
			response_rotation->rotation = rotation_data.rotated;
			control.data_len = 2;
			tx_frame(false);
			break;
			
			//Sing me a song.
		case oi_command_play_song:
			
			#warning "oi_command_play_song is deprecated"
			
			;
			//assuming that we get two data frames, the first containing the notes and the second containing the durations.
			int j;
				struct {
					uint8_t n; //The number of notes present in the song
					//char data[n];
					uint8_t index;
				} *song_data = (void *) &control.data;
		
			//	int j;
		 
			while(rx_frame()) { //this should happen twice please
				char tmp_notes[song_data->n];
				char tmp_durs[song_data->n];
			
				for(j =0; j<song_data->n; j++) {
					//tmp_notes[n]; TODO: broken
					#warning "oi_command_play_song not implemented"
				}

			}
		
			break;

		case oi_command_dump:
			//copies all of the data from OI_UPDATE and transmits to Control.
			oi_update(&(control.oi_state));
			memcpy(control.data, &control.oi_state, sizeof(control.oi_state));
			control.data_len = sizeof(control.oi_state);
			tx_frame(false);
			break;
		
		case oi_command_end_sequence:
			#warning "oi_command_end_sequence not implemented"
			
			// Switch power LED off
			oi_set_leds(1, 1, 0, 0);
			
			wait_ms(50);
			
			// Switch power LED to orange
			oi_set_leds(1, 1, 170, 255);
			
			wait_ms(50);
			
			// Switch power LED off
			oi_set_leds(1, 1, 0, 0);
			
			wait_ms(50);
			
			// Switch power LED to yellow
			oi_set_leds(1, 1, 70, 255);
			
			wait_ms(50);
			
			// Switch power LED off
			oi_set_leds(1, 1, 0, 0);
			
			wait_ms(50);
			
			// Switch power LED back to default state (from oi_init())
			oi_set_leds(1, 1, 7, 255);
			
			// Play song
			songs_load(RICK_ROLL);
			
			break;
		
		default:
			r_error(error_bad_message, "Bad OI Command");
			break;
	}
}
示例#4
0
void
bx_ne2k_c::write_cr(Bit32u value)
{
  BX_DEBUG ("wrote 0x%02x to CR", value);

  // Validate remote-DMA
  if ((value & 0x38) == 0x00) {
    BX_DEBUG("CR write - invalid rDMA value 0");
    value |= 0x20; /* dma_cmd == 4 is a safe default */
	//value = 0x22; /* dma_cmd == 4 is a safe default */
  }

  // Check for s/w reset
  if (value & 0x01) {
    BX_NE2K_THIS s.ISR.reset = 1;
    BX_NE2K_THIS s.CR.stop   = 1;
  } else {
    BX_NE2K_THIS s.CR.stop = 0;
  }

  BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3;
  
  // If start command issued, the RST bit in the ISR
  // must be cleared
  if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) {
    BX_NE2K_THIS s.ISR.reset = 0;
  }

  BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02);
  BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6;

    // Check for send-packet command
    if (BX_NE2K_THIS s.CR.rdma_cmd == 3) {
	// Set up DMA read from receive ring
		BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma =
			BX_NE2K_THIS s.bound_ptr * 256;
		BX_NE2K_THIS s.remote_bytes = *((Bit16u*) &
			BX_NE2K_THIS s.mem[BX_NE2K_THIS s.bound_ptr * 256 + 2 - BX_NE2K_MEMSTART]);
		BX_INFO("Sending buffer #x%x length %d",
			BX_NE2K_THIS s.remote_start,
			BX_NE2K_THIS s.remote_bytes);
    }

  // Check for start-tx
    if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) {
		// loopback mode
		if (BX_NE2K_THIS s.TCR.loop_cntl != 1) {
			BX_INFO("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl);
		} else {
			rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 -
				BX_NE2K_MEMSTART],
				BX_NE2K_THIS s.tx_bytes);

			// do a TX interrupt
			// Generate an interrupt if not masked and not one in progress
			if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) {
				//LOG_MSG("tx complete interrupt");
				PIC_ActivateIRQ(s.base_irq);
			}
			BX_NE2K_THIS s.ISR.pkt_tx = 1;
		}
    } else if (value & 0x04) {
		// start-tx and no loopback
		if (BX_NE2K_THIS s.CR.stop || !BX_NE2K_THIS s.CR.start)
			BX_PANIC(("CR write - tx start, dev in reset"));
	    
		if (BX_NE2K_THIS s.tx_bytes == 0)
			BX_PANIC(("CR write - tx start, tx bytes == 0"));

#ifdef notdef    
    // XXX debug stuff
    printf("packet tx (%d bytes):\t", BX_NE2K_THIS s.tx_bytes);
    for (int i = 0; i < BX_NE2K_THIS s.tx_bytes; i++) {
      printf("%02x ", BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - 
				BX_NE2K_MEMSTART + i]);
      if (i && (((i+1) % 16) == 0)) 
	printf("\t");
    }
    printf("");
#endif    

    // Send the packet to the system driver
	/* TODO: Transmit packet */
    //BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes);
        NE2000_PrivelegeEscalate();
	pcap_sendpacket(adhandle,&s.mem[s.tx_page_start*256 - BX_NE2K_MEMSTART], s.tx_bytes);
        NE2000_PrivelegeDrop();

	// some more debug
	if (BX_NE2K_THIS s.tx_timer_active) {
      BX_PANIC(("CR write, tx timer still active"));
	  PIC_RemoveEvents(NE2000_TX_Event);
	}
	//LOG_MSG("send packet command");
	//s.tx_timer_index = (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10;
	s.tx_timer_active = 1;
	PIC_AddEvent(NE2000_TX_Event,(float)((64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10000.0),0);
    // Schedule a timer to trigger a tx-complete interrupt
    // The number of microseconds is the bit-time / 10.
    // The bit-time is the preamble+sfd (64 bits), the
    // inter-frame gap (96 bits), the CRC (4 bytes), and the
    // the number of bits in the frame (s.tx_bytes * 8).
    //

	/* TODO: Code transmit timer */
	/*
    bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index,
				(64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10,
				0); // not continuous
	*/
  } // end transmit-start branch

  // Linux probes for an interrupt by setting up a remote-DMA read
  // of 0 bytes with remote-DMA completion interrupts enabled.
  // Detect this here
  if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 &&
      BX_NE2K_THIS s.CR.start &&
      BX_NE2K_THIS s.remote_bytes == 0) {
    BX_NE2K_THIS s.ISR.rdma_done = 1;
    if (BX_NE2K_THIS s.IMR.rdma_inte) {
		PIC_ActivateIRQ(s.base_irq);
      //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
    }
  }
}