예제 #1
0
static void cb_parse_object(struct libusb_transfer *transfer)
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);
	char is_method;
	char *name, *afmt, *rfmt;

	check_control(transfer);
	name = (char *) libusb_control_transfer_get_data(transfer);

	is_method = *name++;
	afmt = next(name);
	rfmt = next(afmt);

	slog(4, SLOG_DEBUG, "usb: got %s %s / '%s' '%s'", 
	     is_method ? "method" : "event",
	     name, afmt, rfmt);

	aura_etable_add(inf->etbl, name, 
			is_method ? afmt : NULL, 
			rfmt);

	if (inf->current_object == inf->num_objects) { 
		slog(4, SLOG_DEBUG, "etable becomes active");
		aura_etable_activate(inf->etbl);
		aura_set_status(node, AURA_STATUS_ONLINE);
		inf->state = AUSB_DEVICE_OPERATIONAL;
		itransfer_enable(node, true);
		return;
	}

	slog(4, SLOG_DEBUG, "Requesting info about obj %d", inf->current_object);
	/* Resubmit the transfer for the next round */
	request_object(node, inf->current_object++);
}
예제 #2
0
void LibusbDevice::CtrlTransferCallback(libusb_transfer* transfer)
{
  auto* device = static_cast<LibusbDevice*>(transfer->user_data);
  device->m_transfer_endpoints[0].HandleTransfer(transfer, [&](const auto& cmd) {
    cmd.FillBuffer(libusb_control_transfer_get_data(transfer), transfer->actual_length);
    // The return code is the total transfer length -- *including* the setup packet.
    return transfer->length;
  });
}
예제 #3
0
static void cb_got_dev_info(struct libusb_transfer *transfer)
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);
	struct usb_info_packet *pck; 
	int newbufsize; 
	char *tmp; 

	check_control(transfer);
	slog(4, SLOG_DEBUG, "usb: Got info packet from device");

	if (transfer->actual_length < sizeof(struct usb_info_packet)) { 
		slog(0, SLOG_ERROR, "usb: short-read on info packet want %d got %d  (API mismatch?)",
		     sizeof(struct usb_info_packet), transfer->actual_length);
		usb_panic_and_reset_state(node);
		return; 
	}

	pck = (struct usb_info_packet *)libusb_control_transfer_get_data(transfer);	
	aura_set_node_endian(node, usbdev_is_be(pck) ? 
			     AURA_ENDIAN_BIG : AURA_ENDIAN_LITTLE);

	newbufsize = pck->io_buf_size + LIBUSB_CONTROL_SETUP_SIZE;
	inf->num_objects = pck->num_objs;

	if (newbufsize > inf->io_buf_size) { 
		slog(4, SLOG_DEBUG, "usb: adjusting control buffer size: %d->%d bytes", 
		     inf->io_buf_size, newbufsize);
		tmp = realloc(inf->ctrlbuf, newbufsize);
		if (!tmp) { 
			slog(0, SLOG_ERROR, "Allocation error while adjusting control buffer size");
			aura_panic(node);
		}
		inf->io_buf_size = newbufsize;
		inf->ctrlbuf = (unsigned char *)tmp;
	}
	slog(4, SLOG_DEBUG, "usb: Device has %d objects, now running discovery", inf->num_objects);
	inf->etbl = aura_etable_create(node, inf->num_objects);
	if (!inf->etbl) 
	{
		slog(0, SLOG_ERROR, "usb: etable creation failed");
		aura_panic(node);
	}

	inf->current_object = 0; 
	request_object(node, inf->current_object++);
}
예제 #4
0
static void cb_event_readout_done(struct libusb_transfer *transfer)
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);
	struct usb_event_packet *evt; 
	struct aura_buffer *buf = inf->current_buffer;
	struct aura_object *o; 
 
	if (0 != check_control(transfer))
		goto ignore;

	if (transfer->actual_length < sizeof(struct usb_event_packet))
		goto ignore;
	
	evt = (struct usb_event_packet *) libusb_control_transfer_get_data(transfer);
	o = aura_etable_find_id(node->tbl, evt->id); 
	if (!o) {
		slog(0, SLOG_ERROR, "usb: got bogus event id from device %d, resetting", evt->id);
		goto panic;
	}
	
	if ((transfer->actual_length - LIBUSB_CONTROL_SETUP_SIZE) < 
	    (sizeof(struct usb_event_packet) + o->retlen)) {
		slog(0, SLOG_ERROR, "usb: short read for evt %d: %d bytes expected %d got",
		     evt->id, o->retlen + sizeof(struct usb_event_packet), 
		     transfer->actual_length);
		goto panic;
	}
	
	inf->pending--;
	slog(4, SLOG_DEBUG, "Event readout completed, %d bytes, %d evt left", 
	     transfer->actual_length, inf->pending);
	buf->object = o; 
	/* Position the buffer at the start of the responses */
	buf->pos = LIBUSB_CONTROL_SETUP_SIZE + sizeof(struct usb_event_packet);
	aura_queue_buffer(&node->inbound_buffers, buf);
	return; 

panic: 
	usb_panic_and_reset_state(node);
ignore:
	aura_buffer_release(node, buf);
	inf->current_buffer = NULL;
	return;
}
예제 #5
0
파일: sync.c 프로젝트: ty0924/libusb-1.0
/** \ingroup syncio
 * Perform a USB control transfer.
 *
 * The direction of the transfer is inferred from the bmRequestType field of
 * the setup packet.
 *
 * The wValue, wIndex and wLength fields values should be given in host-endian
 * byte order.
 *
 * \param dev_handle a handle for the device to communicate with
 * \param bmRequestType the request type field for the setup packet
 * \param bRequest the request field for the setup packet
 * \param wValue the value field for the setup packet
 * \param wIndex the index field for the setup packet
 * \param data a suitably-sized data buffer for either input or output
 * (depending on direction bits within bmRequestType)
 * \param wLength the length field for the setup packet. The data buffer should
 * be at least this size.
 * \param timeout timeout (in millseconds) that this function should wait
 * before giving up due to no response being received. For an unlimited
 * timeout, use value 0.
 * \returns on success, the number of bytes actually transferred
 * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
 * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the
 * device
 * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
 * \returns another LIBUSB_ERROR code on other failures
 */
API_EXPORTED int libusb_control_transfer(libusb_device_handle *dev_handle,
	uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
	unsigned char *data, uint16_t wLength, unsigned int timeout)
{
	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
	unsigned char *buffer;
	int completed = 0;
	int r;

	if (!transfer)
		return LIBUSB_ERROR_NO_MEM;

	buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
	if (!buffer) {
		libusb_free_transfer(transfer);
		return LIBUSB_ERROR_NO_MEM;
	}

	libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex,
		wLength);
	if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
		memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);

	libusb_fill_control_transfer(transfer, dev_handle, buffer,
		ctrl_transfer_cb, &completed, timeout);
	transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
	r = libusb_submit_transfer(transfer);
	if (r < 0) {
		libusb_free_transfer(transfer);
		return r;
	}

	while (!completed) {
		r = libusb_handle_events(HANDLE_CTX(dev_handle));
		if (r < 0) {
			if (r == LIBUSB_ERROR_INTERRUPTED)
				continue;
			libusb_cancel_transfer(transfer);
			while (!completed)
				if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0)
					break;
			libusb_free_transfer(transfer);
			return r;
		}
	}

	if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
		memcpy(data, libusb_control_transfer_get_data(transfer),
			transfer->actual_length);

	switch (transfer->status) {
	case LIBUSB_TRANSFER_COMPLETED:
		r = transfer->actual_length;
		break;
	case LIBUSB_TRANSFER_TIMED_OUT:
		r = LIBUSB_ERROR_TIMEOUT;
		break;
	case LIBUSB_TRANSFER_STALL:
		r = LIBUSB_ERROR_PIPE;
		break;
	case LIBUSB_TRANSFER_NO_DEVICE:
		r = LIBUSB_ERROR_NO_DEVICE;
		break;
	default:
		usbi_warn(HANDLE_CTX(dev_handle),
			"unrecognised status code %d", transfer->status);
		r = LIBUSB_ERROR_OTHER;
	}

	libusb_free_transfer(transfer);
	return r;
}
예제 #6
0
파일: usb_con.c 프로젝트: NoPublic/GIMX
void usb_callback(struct libusb_transfer* transfer)
{
  int usb_number = *(int*)transfer->user_data;
  struct usb_state * state = usb_states+usb_number;

  struct libusb_control_setup* setup = libusb_control_transfer_get_setup(transfer);

  if(transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
  {
    if(transfer->status == LIBUSB_TRANSFER_COMPLETED)
    {
      if(setup->bmRequestType & LIBUSB_ENDPOINT_IN)
      {
        if(transfer->actual_length > 0xff)
        {
          fprintf(stderr, "wLength (%hu) is higher than %hu\n", transfer->actual_length, BUFFER_SIZE-LIBUSB_CONTROL_SETUP_SIZE);
        }
        else
        {
          unsigned char *data = libusb_control_transfer_get_data(transfer);
          if(adapter_forward_control_in(usb_number, data, transfer->actual_length) < 0)
          {
            fprintf(stderr, "can't forward control data to the adapter\n");
          }
        }
      }
    }
    else
    {
      if(transfer->status != LIBUSB_TRANSFER_CANCELLED)
      {
        fprintf(stderr, "libusb_transfer failed with status %s (bmRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x)\n", libusb_error_name(transfer->status), setup->bmRequestType, setup->bRequest, setup->wValue);
      }
    }
  }
  else if(transfer->type == LIBUSB_TRANSFER_TYPE_INTERRUPT)
  {
    if(transfer->endpoint == controller[state->type].endpoints.in.address)
    {
      state->ack = 1;
    }

    if(transfer->status == LIBUSB_TRANSFER_COMPLETED)
    {
      if(transfer->endpoint == controller[state->type].endpoints.in.address)
      {
        // process joystick events
        if(transfer->actual_length <= controller[state->type].endpoints.in.size
            && transfer->actual_length > 0)
        {
          process_report(usb_number, state, transfer);
        }
      }
    }
    else
    {
      if(transfer->status != LIBUSB_TRANSFER_TIMED_OUT && transfer->status != LIBUSB_TRANSFER_CANCELLED)
      {
        fprintf(stderr, "libusb_transfer failed with status %s (endpoint=0x%02x)\n", libusb_error_name(transfer->status), transfer->endpoint);
      }
    }
  }

  remove_transfer(transfer);
}