Beispiel #1
0
void client_send_red_brick_enumerate(Client *client, EnumerationType type) {
    EnumerateCallback enumerate_callback;
    uint32_t uid = red_usb_gadget_get_uid(); // always little endian

    memset(&enumerate_callback, 0, sizeof(enumerate_callback));

    enumerate_callback.header.uid = uid;
    enumerate_callback.header.length = sizeof(enumerate_callback);
    enumerate_callback.header.function_id = CALLBACK_ENUMERATE;
    packet_header_set_sequence_number(&enumerate_callback.header, 0);
    packet_header_set_response_expected(&enumerate_callback.header, true);

    base58_encode(enumerate_callback.uid, uint32_from_le(uid));
    enumerate_callback.connected_uid[0] = '0';
    enumerate_callback.position = '0';
    enumerate_callback.hardware_version[0] = 1; // FIXME
    enumerate_callback.hardware_version[1] = 0;
    enumerate_callback.hardware_version[2] = 0;
    enumerate_callback.firmware_version[0] = _redapid_version[0];
    enumerate_callback.firmware_version[1] = _redapid_version[1];
    enumerate_callback.firmware_version[2] = _redapid_version[2];
    enumerate_callback.device_identifier = uint16_to_le(RED_BRICK_DEVICE_IDENTIFIER);
    enumerate_callback.enumeration_type = type;

    client_dispatch_response(client, NULL, (Packet *)&enumerate_callback, true, false);
}
Beispiel #2
0
// drop all pending requests for the given UID from the global list
static void network_drop_pending_requests(uint32_t uid) {
	Node *pending_request_global_node = _pending_request_sentinel.next;
	Node *pending_request_global_node_next;
	PendingRequest *pending_request;
	char base58[BASE58_MAX_LENGTH];
	int count = 0;

	while (pending_request_global_node != &_pending_request_sentinel) {
		pending_request = containerof(pending_request_global_node,
		                              PendingRequest, global_node);
		pending_request_global_node_next = pending_request_global_node->next;

		if (pending_request->header.uid == uid) {
			pending_request_remove_and_free(pending_request);

			++count;
		}

		pending_request_global_node = pending_request_global_node_next;
	}

	if (count > 0) {
		log_warn("Dropped %d pending request(s) (uid: %s)",
		         count, base58_encode(base58, uint32_from_le(uid)));
	}
}
Beispiel #3
0
static void client_handle_request(Client *client, Packet *request) {
    char packet_signature[PACKET_MAX_SIGNATURE_LENGTH];
    EmptyResponse response;

    // handle requests meant for brickd
    if (uint32_from_le(request->header.uid) == UID_BRICK_DAEMON) {
        // add as pending request if response is expected
        if (packet_header_get_response_expected(&request->header)) {
            network_client_expects_response(client, request);
        }

        if (request->header.function_id == FUNCTION_GET_AUTHENTICATION_NONCE) {
            if (request->header.length != sizeof(GetAuthenticationNonceRequest)) {
                log_error("Received authentication-nonce request (%s) from client ("CLIENT_SIGNATURE_FORMAT") with wrong length, disconnecting client",
                          packet_get_request_signature(packet_signature, request),
                          client_expand_signature(client));

                client->disconnected = true;

                return;
            }

            client_handle_get_authentication_nonce_request(client, (GetAuthenticationNonceRequest *)request);
        } else if (request->header.function_id == FUNCTION_AUTHENTICATE) {
            if (request->header.length != sizeof(AuthenticateRequest)) {
                log_error("Received authenticate request (%s) from client ("CLIENT_SIGNATURE_FORMAT") with wrong length, disconnecting client",
                          packet_get_request_signature(packet_signature, request),
                          client_expand_signature(client));

                client->disconnected = true;

                return;
            }

            client_handle_authenticate_request(client, (AuthenticateRequest *)request);
        } else {
            response.header = request->header;
            response.header.length = sizeof(response);

            packet_header_set_error_code(&response.header,
                                         PACKET_E_FUNCTION_NOT_SUPPORTED);

            client_dispatch_response(client, NULL, (Packet *)&response, false, false);
        }
    } else if (client->authentication_state == CLIENT_AUTHENTICATION_STATE_DISABLED ||
               client->authentication_state == CLIENT_AUTHENTICATION_STATE_DONE) {
        // add as pending request if response is expected...
        if (packet_header_get_response_expected(&request->header)) {
            network_client_expects_response(client, request);
        }

        // ...then dispatch it to the hardware
        hardware_dispatch_request(request);
    } else {
        log_packet_debug("Client ("CLIENT_SIGNATURE_FORMAT") is not authenticated, dropping request (%s)",
                         client_expand_signature(client),
                         packet_get_request_signature(packet_signature, request));
    }
}
Beispiel #4
0
static uint32_t
read_le_u32 (riff_context *ctxt)
{
  uint32_t tmp;

  if (fread (&tmp, sizeof (uint32_t), 1, ctxt->fd) != 1)
    vcd_error ("fread () failed");

  return uint32_from_le (tmp);
}
Beispiel #5
0
bool
udf_get_lba(const udf_file_entry_t *p_udf_fe,
	    /*out*/ uint32_t *start, /*out*/ uint32_t *end)
{
  if (! p_udf_fe->i_alloc_descs)
    return false;

  switch (p_udf_fe->icb_tag.flags & ICBTAG_FLAG_AD_MASK) {
  case ICBTAG_FLAG_AD_SHORT:
    {
      /* The allocation descriptor field is filled with short_ad's. */
      udf_short_ad_t *p_ad = (udf_short_ad_t *)
	(p_udf_fe->u.ext_attr + uint32_from_le(p_udf_fe->i_extended_attr));

      *start = uint32_from_le(p_ad->pos);
      *end = *start +
	((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
      return true;
    }
    break;
  case ICBTAG_FLAG_AD_LONG:
    {
      /* The allocation descriptor field is filled with long_ad's */
      udf_long_ad_t *p_ad = (udf_long_ad_t *)
	(p_udf_fe->u.ext_attr + uint32_from_le(p_udf_fe->i_extended_attr));

      *start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */
      *end = *start +
	((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
      return true;
    }
    break;
  case ICBTAG_FLAG_AD_EXTENDED:
    {
      udf_ext_ad_t *p_ad = (udf_ext_ad_t *)
	(p_udf_fe->u.ext_attr + uint32_from_le(p_udf_fe->i_extended_attr));

      *start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition number */
      *end = *start +
	((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
      return true;
    }
    break;
  default:
    return false;
  }
  return false;
}
Beispiel #6
0
static void red_stack_spi_insert_position(REDStackSlave *slave) {
	if (_red_stack.packet_from_spi.header.function_id == CALLBACK_ENUMERATE ||
	    _red_stack.packet_from_spi.header.function_id == FUNCTION_GET_IDENTITY) {
		EnumerateCallback *enum_cb = (EnumerateCallback *)&_red_stack.packet_from_spi;

		if (enum_cb->position == '0') {
			enum_cb->position = '0' + slave->stack_address + 1;
			base58_encode(enum_cb->connected_uid, uint32_from_le(red_usb_gadget_get_uid()));
		}
	}
}
Beispiel #7
0
Datei: udf.c Projekt: hanji/rufus
/*!
  Returns POSIX mode bitstring for a given file.
*/
mode_t 
udf_get_posix_filemode(const udf_dirent_t *p_udf_dirent) 
{
  udf_file_entry_t udf_fe;
  mode_t mode = 0;

  if (udf_get_file_entry(p_udf_dirent, &udf_fe)) {
    uint32_t i_perms;
#ifdef S_ISUID
    uint16_t i_flags;

    i_flags = uint16_from_le(udf_fe.icb_tag.flags);
#endif
    i_perms = uint32_from_le(udf_fe.permissions);

    if (i_perms & FE_PERM_U_READ)  mode |= S_IRUSR;
    if (i_perms & FE_PERM_U_WRITE) mode |= S_IWUSR;
    if (i_perms & FE_PERM_U_EXEC)  mode |= S_IXUSR;
    
#ifdef S_IRGRP
    if (i_perms & FE_PERM_G_READ)  mode |= S_IRGRP;
    if (i_perms & FE_PERM_G_WRITE) mode |= S_IWGRP;
    if (i_perms & FE_PERM_G_EXEC)  mode |= S_IXGRP;
#endif
    
#ifdef S_IROTH
    if (i_perms & FE_PERM_O_READ)  mode |= S_IROTH;
    if (i_perms & FE_PERM_O_WRITE) mode |= S_IWOTH;
    if (i_perms & FE_PERM_O_EXEC)  mode |= S_IXOTH;
#endif

    switch (udf_fe.icb_tag.file_type) {
    case ICBTAG_FILE_TYPE_DIRECTORY: 
      mode |= S_IFDIR;
      break;
    case ICBTAG_FILE_TYPE_REGULAR:
      mode |= S_IFREG;
      break;
#ifdef S_IFLNK
    case ICBTAG_FILE_TYPE_SYMLINK:
      mode |= S_IFLNK;
      break;
#endif
    case ICBTAG_FILE_TYPE_CHAR:
      mode |= S_IFCHR;
      break;
#ifdef S_IFSOCK
    case ICBTAG_FILE_TYPE_SOCKET:
      mode |= S_IFSOCK;
      break;
#endif
    case ICBTAG_FILE_TYPE_BLOCK:
      mode |= S_IFBLK;
      break;
    default: ;
    };
  
#ifdef S_ISUID
    if (i_flags & ICBTAG_FLAG_SETUID) mode |= S_ISUID;
    if (i_flags & ICBTAG_FLAG_SETGID) mode |= S_ISGID;
    if (i_flags & ICBTAG_FLAG_STICKY) mode |= S_ISVTX;
#endif
  }
  
  return mode;
  
}
Beispiel #8
0
/*
 * Translate a file offset into a logical block and then into a physical
 * block.
 */
static lba_t
offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, 
	      /*out*/ lba_t *pi_lba, /*out*/ uint32_t *pi_max_size)
{
  udf_t *p_udf = p_udf_dirent->p_udf;
  const udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) 
    &p_udf_dirent->fe;
  const udf_icbtag_t *p_icb_tag = &p_udf_fe->icb_tag;
  const uint16_t strat_type= uint16_from_le(p_icb_tag->strat_type);
  
  switch (strat_type) {
  case 4096:
    printf("Cannot deal with strategy4096 yet!\n");
    return CDIO_INVALID_LBA;
    break;
  case ICBTAG_STRATEGY_TYPE_4:
    {
      uint32_t icblen = 0;
      lba_t lsector;
      int ad_offset, ad_num = 0;
      uint16_t addr_ilk = uint16_from_le(p_icb_tag->flags&ICBTAG_FLAG_AD_MASK);
      
      switch (addr_ilk) {
      case ICBTAG_FLAG_AD_SHORT: 
	{
	  udf_short_ad_t *p_icb;
	  /*
	   * The allocation descriptor field is filled with short_ad's.
	   * If the offset is beyond the current extent, look for the
	   * next extent.
	   */
	  do {
	    i_offset -= icblen;
	    ad_offset = sizeof(udf_short_ad_t) * ad_num;
	    if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) {
	      printf("File offset out of bounds\n");
	      return CDIO_INVALID_LBA;
	    }
	    p_icb = (udf_short_ad_t *) 
	      GETICB( uint32_from_le(p_udf_fe->i_extended_attr) 
		      + ad_offset );
	    icblen = p_icb->len;
	    ad_num++;
	  } while(i_offset >= icblen);
	  
	  lsector = (i_offset / UDF_BLOCKSIZE) + p_icb->pos;
	  
	  *pi_max_size = p_icb->len;
	}
	break;
      case ICBTAG_FLAG_AD_LONG: 
	{
	  /*
	   * The allocation descriptor field is filled with long_ad's
	   * If the i_offset is beyond the current extent, look for the
	   * next extent.
	   */
	  udf_long_ad_t *p_icb;
	  do {
	    i_offset -= icblen;
	    ad_offset = sizeof(udf_long_ad_t) * ad_num;
	    if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) {
	      printf("File offset out of bounds\n");
	      return CDIO_INVALID_LBA;
	    }
	    p_icb = (udf_long_ad_t *) 
	      GETICB( uint32_from_le(p_udf_fe->i_extended_attr)
		      + ad_offset );
	    icblen = p_icb->len;
	    ad_num++;
	  } while(i_offset >= icblen);
	
	  lsector = (i_offset / UDF_BLOCKSIZE) +
	    uint32_from_le(((udf_long_ad_t *)(p_icb))->loc.lba);
	  
	  *pi_max_size = p_icb->len;
	}
	break;
      case ICBTAG_FLAG_AD_IN_ICB:
	/*
	 * This type means that the file *data* is stored in the
	 * allocation descriptor field of the file entry.
	 */
	*pi_max_size = 0;
	printf("Don't know how to data in ICB handle yet\n");
	return CDIO_INVALID_LBA;
      case ICBTAG_FLAG_AD_EXTENDED:
	printf("Don't know how to handle extended addresses yet\n");
	return CDIO_INVALID_LBA;
      default:
	printf("Unsupported allocation descriptor %d\n", addr_ilk);
	return CDIO_INVALID_LBA;
      }
      
      *pi_lba = lsector + p_udf->i_part_start;
      return *pi_lba;
    }
  default:
    printf("Unknown strategy type %d\n", strat_type);
    return DRIVER_OP_ERROR;
  }
}
Beispiel #9
0
// If data should just be polled, set packet_send to NULL.
//
// If no packet is received from slave the length in packet_recv will be set to 0,
// the exact reason for that is encoded in the return value.
//
// For the return value see RED_STACK_TRANSCEIVE_RESULT_* at the top of this file.
static int red_stack_spi_transceive_message(REDStackPacket *packet_send, Packet *packet_recv, REDStackSlave *slave) {
	int retval = 0;
	uint8_t length, length_send;
	uint8_t checksum;
	int rc;
	uint8_t sequence_number_master = 0xFF;
	uint8_t sequence_number_slave = 0xFF;

	uint8_t tx[RED_STACK_SPI_PACKET_SIZE] = {0};
	uint8_t rx[RED_STACK_SPI_PACKET_SIZE] = {0};

	// We assume that we don't receive anything. If we receive a packet the
	// length will be overwritten again
	packet_recv->header.length = 0;

	// Preamble is always the same
	tx[RED_STACK_SPI_PREAMBLE] = RED_STACK_SPI_PREAMBLE_VALUE;

	if (packet_send == NULL) {
		// If packet_send is NULL
		// we send a message with empty payload (4 byte)
		tx[RED_STACK_SPI_LENGTH] = RED_STACK_SPI_PACKET_EMPTY_SIZE;
		retval = RED_STACK_TRANSCEIVE_RESULT_SEND_NONE;
	} else if (slave->status == RED_STACK_SLAVE_STATUS_AVAILABLE) {
		length = packet_send->packet.header.length;

		if (length > sizeof(Packet)) {
			retval |= RED_STACK_TRANSCEIVE_RESULT_SEND_ERROR;
			log_error("Send length is greater then allowed (actual: %d > maximum: %d)",
			          length, (int)sizeof(Packet));
			goto ret;
		}

		retval = RED_STACK_TRANSCEIVE_DATA_SEND;

		tx[RED_STACK_SPI_LENGTH] = length + RED_STACK_SPI_PACKET_EMPTY_SIZE;
		memcpy(tx+2, &packet_send->packet, length);
	} else {
		retval = RED_STACK_TRANSCEIVE_RESULT_SEND_ERROR;
		log_error("Slave with stack address %d is not present in stack", slave->stack_address);
		goto ret;
	}

	length = tx[RED_STACK_SPI_LENGTH];

	// Set master and slave sequence number
	tx[RED_STACK_SPI_INFO(length)] = slave->sequence_number_master | slave->sequence_number_slave;

	// Calculate checksum
	tx[RED_STACK_SPI_CHECKSUM(length)] = red_stack_spi_calculate_pearson_hash(tx, length-1);

	struct spi_ioc_transfer spi_transfer = {
		.tx_buf = (unsigned long)&tx,
		.rx_buf = (unsigned long)&rx,
		.len = RED_STACK_SPI_PACKET_SIZE,
	};

	red_stack_spi_select(slave);
	rc = ioctl(_red_stack_spi_fd, SPI_IOC_MESSAGE(1), &spi_transfer);
	red_stack_spi_deselect(slave);

	if (rc < 0) {
		// Overwrite current return status with error,
		// it seems ioctl itself didn't work.
		retval = RED_STACK_TRANSCEIVE_RESULT_SEND_ERROR | RED_STACK_TRANSCEIVE_RESULT_READ_ERROR;
		if(packet_send == NULL) {
			slave->next_packet_empty = true;
		}
		log_error("ioctl failed: %s (%d)", get_errno_name(errno), errno);
		goto ret;
	}

	length_send = rc;

	if (length_send != RED_STACK_SPI_PACKET_SIZE) {
		// Overwrite current return status with error,
		// it seems ioctl itself didn't work.
		retval = RED_STACK_TRANSCEIVE_RESULT_SEND_ERROR | RED_STACK_TRANSCEIVE_RESULT_READ_ERROR;
		if(packet_send == NULL) {
			slave->next_packet_empty = true;
		}
		log_error("ioctl has unexpected result (actual: %d != expected: %d)",
		          length_send, RED_STACK_SPI_PACKET_SIZE);
		goto ret;
	}

	if (rx[RED_STACK_SPI_PREAMBLE] != RED_STACK_SPI_PREAMBLE_VALUE) {
		// Do not log by default, an "unproper preamble" is part of the protocol
		// if the slave is too busy to fill the DMA buffers fast enough
		// log_error("Received packet without proper preamble (actual: %d != expected: %d)",
		//          rx[RED_STACK_SPI_PREAMBLE], RED_STACK_SPI_PREAMBLE_VALUE);
		retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_ERROR;
		if(packet_send == NULL) {
			slave->next_packet_empty = true;
		}
		goto ret;
	}

	// Check length
	length = rx[RED_STACK_SPI_LENGTH];

	if ((length != RED_STACK_SPI_PACKET_EMPTY_SIZE) &&
	    ((length < (RED_STACK_SPI_PACKET_EMPTY_SIZE + sizeof(PacketHeader))) ||
	     (length > RED_STACK_SPI_PACKET_SIZE))) {
		log_error("Received packet with malformed length: %d", length);
		retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_ERROR;
		if(packet_send == NULL) {
			slave->next_packet_empty = true;
		}
		goto ret;
	}

	// Calculate and check checksum
	checksum = red_stack_spi_calculate_pearson_hash(rx, length-1);

	if (checksum != rx[RED_STACK_SPI_CHECKSUM(length)]) {
		log_error("Received packet with wrong checksum (actual: %x != expected: %x)",
		          checksum, rx[RED_STACK_SPI_CHECKSUM(length)]);
		retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_ERROR;
		if(packet_send == NULL) {
			slave->next_packet_empty = true;
		}
		goto ret;
	}

	// If we send data and the master sequence number matches to the one
	// set in the packet we know that the slave received the packet!
	if ((packet_send != NULL) /*&& (packet_send->status == RED_STACK_PACKET_STATUS_SEQUENCE_NUMBER_SET)*/) {
		sequence_number_master = rx[RED_STACK_SPI_INFO(length)] & RED_STACK_SPI_INFO_SEQUENCE_MASTER_MASK;

		if (sequence_number_master == slave->sequence_number_master) {
			retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_SEND)) | RED_STACK_TRANSCEIVE_RESULT_SEND_OK;

			// Increase sequence number for next packet
			red_stack_increase_master_sequence_number(slave);
		}
	} else {
		// If we didn't send anything we can always increase the sequence number,
		// it doesn't matter if the slave actually received it.
		red_stack_increase_master_sequence_number(slave);
	}

	// If the slave sequence number matches we already processed this packet
	sequence_number_slave = rx[RED_STACK_SPI_INFO(length)] & RED_STACK_SPI_INFO_SEQUENCE_SLAVE_MASK;

	if (sequence_number_slave == slave->sequence_number_slave) {
		retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_NONE;
	} else {
		// Otherwise we save the new sequence number
		slave->sequence_number_slave = sequence_number_slave;

		if (length == RED_STACK_SPI_PACKET_EMPTY_SIZE) {
			// Do not log by default, will produce 2000 log entries per second
			// log_packet_debug("Received empty packet over SPI (w/ header)");
			retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_NONE;
		} else {
			// Everything seems OK, we can copy to buffer
			memcpy(packet_recv, rx+2, length - RED_STACK_SPI_PACKET_EMPTY_SIZE);
			log_packet_debug("Received packet over SPI (%s)",
			                 packet_get_response_signature(packet_signature, packet_recv));
			retval = (retval & (~RED_STACK_TRANSCEIVE_RESULT_MASK_READ)) | RED_STACK_TRANSCEIVE_RESULT_READ_OK;
			retval |= RED_STACK_TRANSCEIVE_DATA_RECEIVED;
		}
	}

ret:
	return retval;
}

// Creates the "routing table", which is just the
// array of REDStackSlave structures.
static void red_stack_spi_create_routing_table(void) {
	char base58[BASE58_MAX_LENGTH];
	int tries, ret, i;
	uint8_t stack_address = 0;
	uint8_t uid_counter = 0;

	log_debug("Starting to discover SPI stack slaves");

	while (stack_address < RED_STACK_SPI_MAX_SLAVES) {
		REDStackSlave *slave = &_red_stack.slaves[stack_address];

		Packet packet;
		StackEnumerateResponse *response;

		REDStackPacket red_stack_packet = {
			slave,
			{{
				0,   // UID 0
				sizeof(StackEnumerateRequest),
				FUNCTION_STACK_ENUMERATE,
				0x08, // Return expected
				0
			}, {0}, {0}},
			RED_STACK_PACKET_STATUS_ADDED,
		};

		// We have to assume that the slave is available
		slave->status = RED_STACK_SLAVE_STATUS_AVAILABLE;

		// Send stack enumerate request
		for (tries = 0; tries < RED_STACK_SPI_ROUTING_TRIES; tries++) {
			ret = red_stack_spi_transceive_message(&red_stack_packet, &packet, slave);

			if ((ret & RED_STACK_TRANSCEIVE_RESULT_MASK_SEND) == RED_STACK_TRANSCEIVE_RESULT_SEND_OK) {
				break;
			}

			SLEEP_NS(0, RED_STACK_SPI_ROUTING_WAIT); // Give slave some more time
		}

		if (tries == RED_STACK_SPI_ROUTING_TRIES) {
			// Slave does not seem to be available,
			slave->status = RED_STACK_SLAVE_STATUS_ABSENT;
			// This means that there can't be any more slaves above
			// and we are actually done here already!
			break;
		}

		// Receive stack enumerate response
		for (tries = 0; tries < RED_STACK_SPI_ROUTING_TRIES; tries++) {
			// We first check if we already received an answer before we try again
			if ((ret & RED_STACK_TRANSCEIVE_RESULT_MASK_READ) == RED_STACK_TRANSCEIVE_RESULT_READ_OK) {
				break;
			}

			// Here we sleep before transceive so that there is some time
			// between the sending of stack enumerate and the receiving
			// of the answer
			SLEEP_NS(0, RED_STACK_SPI_ROUTING_WAIT); // Give slave some more time

			ret = red_stack_spi_transceive_message(NULL, &packet, slave);
		}

		if (tries == RED_STACK_SPI_ROUTING_TRIES) {
			// Slave does not seem to be available,
			slave->status = RED_STACK_SLAVE_STATUS_ABSENT;
			// This means that there can't be any more slaves above
			// and we are actually done here already!
			break;
		}

		response = (StackEnumerateResponse *)&packet;

		for (i = 0; i < PACKET_MAX_STACK_ENUMERATE_UIDS; i++) {
			if (response->uids[i] != 0) {
				uid_counter++;
				stack_add_recipient(&_red_stack.base, response->uids[i], stack_address);
				log_debug("Found UID number %d of slave %d with UID %s",
				          i, stack_address,
				          base58_encode(base58, uint32_from_le(response->uids[i])));
			} else {
				break;
			}
		}

		stack_address++;
	}

	_red_stack.slave_num = stack_address;

	log_info("SPI stack slave discovery done. Found %d slave(s) with %d UID(s) in total",
	         stack_address, uid_counter);
}
Beispiel #10
0
udf_dirent_t *
udf_readdir(udf_dirent_t *p_udf_dirent)
{
  udf_t *p_udf;
  uint8_t* p;

  if (p_udf_dirent->dir_left <= 0) {
    udf_dirent_free(p_udf_dirent);
    return NULL;
  }

  /* file position must be reset when accessing a new file */
  p_udf = p_udf_dirent->p_udf;
  p_udf->i_position = 0;

  if (p_udf_dirent->fid) {
    /* advance to next File Identifier Descriptor */
    /* FIXME: need to advance file entry (fe) as well.  */
    uint32_t ofs = 4 *
      ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->u.i_imp_use
	+ p_udf_dirent->fid->i_file_id + 3) / 4);

    p_udf_dirent->fid =
      (udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs);
  }

  if (!p_udf_dirent->fid) {
    uint32_t i_sectors =
      (p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1);
    uint32_t size = UDF_BLOCKSIZE * i_sectors;
    driver_return_code_t i_ret;

    if (!p_udf_dirent->sector)
      p_udf_dirent->sector = (uint8_t*) malloc(size);
    i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector,
			     p_udf_dirent->i_part_start+p_udf_dirent->i_loc,
			     i_sectors);
    if (DRIVER_OP_SUCCESS == i_ret)
      p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector;
    else
      p_udf_dirent->fid = NULL;
  }

  if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID))
    {
      uint32_t ofs =
	4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->u.i_imp_use
	      + p_udf_dirent->fid->i_file_id + 3) / 4);

      p_udf_dirent->dir_left -= ofs;
      p_udf_dirent->b_dir =
	(p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
      p_udf_dirent->b_parent =
	(p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0;

      {
	const unsigned int i_len = p_udf_dirent->fid->i_file_id;

	if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start
			 + uint32_from_le(p_udf_dirent->fid->icb.loc.lba), 1)) {
		udf_dirent_free(p_udf_dirent);
		return NULL;
	}

       free_and_null(p_udf_dirent->psz_name);
       p = (uint8_t*)p_udf_dirent->fid->u.imp_use.data + p_udf_dirent->fid->u.i_imp_use;
       p_udf_dirent->psz_name = unicode16_decode(p, i_len);
      }
      return p_udf_dirent;
    }
  udf_dirent_free(p_udf_dirent);
  return NULL;
}
Beispiel #11
0
/*!
  Get the root in p_udf. If b_any_partition is false then
  the root must be in the given partition.
  NULL is returned if the partition is not found or a root is not found or
  there is on error.

  Caller must free result - use udf_dirent_free for that.
*/
udf_dirent_t *
udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
{
  const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;
  const uint32_t mvds_start =
    uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
  const uint32_t mvds_end   = mvds_start +
    (uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
  uint32_t i_lba;
  uint8_t data[UDF_BLOCKSIZE];

  /*
     Now we have the joy of finding the Partition Descriptor and the
     Logical Volume Descriptor for the Main Volume Descriptor
     Sequence. Once we've got that, we use the Logical Volume
     Descriptor to get a Fileset Descriptor and that has the Root
     Directory File Entry.
  */
  for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
    uint8_t data2[UDF_BLOCKSIZE];

    partition_desc_t *p_partition = (partition_desc_t *) &data2;

    if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_partition, i_lba, 1) )
      return NULL;

    if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) {
      const partition_num_t i_partition_check
	= uint16_from_le(p_partition->number);
      if (b_any_partition || i_partition_check == i_partition) {
	/* Squirrel away some data regarding partition */
	p_udf->i_partition = uint16_from_le(p_partition->number);
	p_udf->i_part_start = uint32_from_le(p_partition->start_loc);
	if (p_udf->lvd_lba) break;
      }
    } else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) {
      /* Get fileset descriptor */
      logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data2;
      bool b_valid =
	UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize);

      if (b_valid) {
	p_udf->lvd_lba = i_lba;
	p_udf->fsd_offset =
	  uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba);
	if (p_udf->i_part_start) break;
      }
    }
  }
  if (p_udf->lvd_lba && p_udf->i_part_start) {
    udf_fsd_t *p_fsd = (udf_fsd_t *) &data;

    driver_return_code_t ret =
      udf_read_sectors(p_udf, p_fsd, p_udf->i_part_start + p_udf->fsd_offset,
		       1);

    if (DRIVER_OP_SUCCESS == ret && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
      udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data;
      const uint32_t parent_icb = uint32_from_le(p_fsd->root_icb.loc.lba);

      /* Check partition numbers match of last-read block?  */

      ret = udf_read_sectors(p_udf, p_udf_fe,
			     p_udf->i_part_start + parent_icb, 1);
      if (ret == DRIVER_OP_SUCCESS &&
	  !udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) {

	/* Check partition numbers match of last-read block? */

	/* We win! - Save root directory information. */
	return udf_new_dirent(p_udf_fe, p_udf, "/", true, false );
      }
    }
  }

  return NULL;
}
Beispiel #12
0
/*!
  Open an UDF for reading. Maybe in the future we will have
  a mode. NULL is returned on error.

  Caller must free result - use udf_close for that.
*/
udf_t *
udf_open (const char *psz_path)
{
  udf_t *p_udf = (udf_t *) calloc(1, sizeof(udf_t)) ;
  uint8_t data[UDF_BLOCKSIZE];

  if (!p_udf) return NULL;

  /* Sanity check */
  cdio_assert(sizeof(udf_file_entry_t) == UDF_BLOCKSIZE);

  p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN);
  if (!p_udf->cdio) {
    /* Not a CD-ROM drive or CD Image. Maybe it's a UDF file not
       encapsulated as a CD-ROM Image (e.g. often .UDF or (sic) .ISO)
    */
    p_udf->stream = cdio_stdio_new( psz_path );
    if (!p_udf->stream)
      goto error;
    p_udf->b_stream = true;
  }

  /*
   * Look for an Anchor Volume Descriptor Pointer at sector 256.
   */
  if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, &data, 256, 1) )
    goto error;

  memcpy(&(p_udf->anchor_vol_desc_ptr), &data, sizeof(anchor_vol_desc_ptr_t));

  if (udf_checktag((udf_tag_t *)&(p_udf->anchor_vol_desc_ptr), TAGID_ANCHOR))
    goto error;

  /*
   * Then try to find a reference to a Primary Volume Descriptor.
   */
  {
    anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;

    const uint32_t mvds_start =
      uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
    const uint32_t mvds_end   = mvds_start +
      (uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;

    uint32_t i_lba;

    for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
      udf_pvd_t *p_pvd = (udf_pvd_t *) &data;

      if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_pvd, i_lba, 1) )
	goto error;

      if (!udf_checktag(&p_pvd->tag, TAGID_PRI_VOL)) {
	p_udf->pvd_lba = i_lba;
	break;
      }

    }

    /*
     * If we couldn't find a reference, bail out.
     */
    if (i_lba == mvds_end)
      goto error;
  }

  return p_udf;

 error:
  cdio_stdio_destroy(p_udf->stream);
  free(p_udf);
  return NULL;
}
Beispiel #13
0
// New packet from BrickletStack is send into brickd event loop
static void bricklet_stack_dispatch_from_spi(void *opaque) {
	BrickletStack *bricklet_stack = (BrickletStack*)opaque;
	int i;
	eventfd_t ev;
	Packet *packet;

	(void)opaque;

	// handle at most 5 queued responses at once to avoid blocking the event
	// loop for too long
	for (i = 0; i < 5; ++i) {
		if (eventfd_read(bricklet_stack->notification_event, &ev) < 0) {
			if (errno_would_block()) {
				return; // no queue responses left
			}

			log_error("Could not read from SPI notification event: %s (%d)",
			          get_errno_name(errno), errno);

			return;
		}

		mutex_lock(&bricklet_stack->response_queue_mutex);
		packet = queue_peek(&bricklet_stack->response_queue);
		mutex_unlock(&bricklet_stack->response_queue_mutex);

		if (packet == NULL) { // eventfd indicates a response but queue is empty
			log_error("Response queue and notification event are out-of-sync");

			return;
		}

		// Update routing table (this is necessary for Co-MCU Bricklets)
		if (packet->header.function_id == CALLBACK_ENUMERATE) {
			stack_add_recipient(&bricklet_stack->base, packet->header.uid, 0);
		}

		if ((packet->header.function_id == CALLBACK_ENUMERATE) ||
		    (packet->header.function_id == FUNCTION_GET_IDENTITY)) {
			EnumerateCallback *ec = (EnumerateCallback*)packet;

			// If the Bricklet is a HAT Brick (ID 111) or HAT Zero Brick (ID 112)
			// we update the connected_uid.
			if((ec->device_identifier == 111) || (ec->device_identifier == 112)) {
				*bricklet_stack->config.connected_uid = ec->header.uid;
			}

			// If the Bricklet is connected to an isolator we don't have to
			// update the position and the connected UID. this is already
			// done by the isolator itself.
			if(ec->position != 'Z' || ec->connected_uid[0] == '\0') {
				memcpy(ec->connected_uid, PACKET_NO_CONNECTED_UID_STR, PACKET_NO_CONNECTED_UID_STR_LENGTH);
				if((*bricklet_stack->config.connected_uid != 0) && (ec->device_identifier != 111) && (ec->device_identifier != 112)) {
					char base58[BASE58_MAX_LENGTH];
					base58_encode(base58, uint32_from_le(*bricklet_stack->config.connected_uid));
					strncpy(ec->connected_uid, base58, BASE58_MAX_LENGTH);
				}

				ec->position = 'a' + bricklet_stack->config.num;
			}
		}

		// Send message into brickd dispatcher
		network_dispatch_response(packet);
		bricklet_stack->data_seen = true;

		mutex_lock(&bricklet_stack->response_queue_mutex);
		queue_pop(&bricklet_stack->response_queue, NULL);
		mutex_unlock(&bricklet_stack->response_queue_mutex);
	}
}