Пример #1
0
static void cb_call_write_done(struct libusb_transfer *transfer)
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);

	if (0 != check_control(transfer)) { 
		/* Put it back to queue. Core will deal with it later */
		goto requeue;
	}

	if (transfer->actual_length - LIBUSB_CONTROL_SETUP_SIZE < transfer->length) { 
		slog(0, SLOG_ERROR, "usb: short-write on call packet want %d got %d  (API mismatch?)",
		     transfer->length, transfer->actual_length);
		usb_panic_and_reset_state(node);
		goto requeue;
	}

	aura_buffer_release(node, inf->current_buffer);
	inf->current_buffer = NULL;
	slog(4, SLOG_DEBUG, "Call write done");
	return;
requeue:
	aura_requeue_buffer(&node->outbound_buffers, inf->current_buffer);
	inf->current_buffer = NULL;
}
Пример #2
0
static void usb_stop_ops(void *arg)
{
	struct usb_dev_info *inf = arg;

	usb_panic_and_reset_state(inf->node);
	slog(2, SLOG_INFO, "susb: Device disconnect detected!");
	susb_offline_transport(inf);
}
Пример #3
0
static void submit_control(struct aura_node *node)
{
	int ret; 
	struct usb_dev_info *inf = aura_get_transportdata(node);

	ret = libusb_submit_transfer(inf->ctransfer);
	if (ret!= 0) {
		slog(0, SLOG_ERROR, "usb: error submitting control transfer");
		usb_panic_and_reset_state(node);
	}
	inf->cbusy=true;
}
Пример #4
0
static void submit_interrupt(struct aura_node *node)
{
	struct usb_dev_info *inf = aura_get_transportdata(node);
	int ret; 
	if (inf->ibusy)
		return;
	ret = libusb_submit_transfer(inf->itransfer);
	inf->ibusy = true;
	if (ret!= 0) {
		slog(0, SLOG_ERROR, "usb: error submitting interrupt transfer");
		usb_panic_and_reset_state(node);
	}
}
Пример #5
0
static int check_control(struct libusb_transfer *transfer) 
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);
	int ret = 0; 

	inf->cbusy = false; 
		
	if (failing(inf) || (transfer->status != LIBUSB_TRANSFER_COMPLETED)) {
		usb_panic_and_reset_state(node);
		ret = -EIO;
	}
	return ret; 
}
Пример #6
0
static void itransfer_enable(struct aura_node *node, bool enable)
{
	struct usb_dev_info *inf = aura_get_transportdata(node);

	inf->itransfer_enabled = enable;
	if (failing(inf)) {
		usb_panic_and_reset_state(node);
		return;
	}

	if (!enable) 
		return; 
	
	submit_interrupt(node);
}
Пример #7
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++);
}
Пример #8
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;
}
Пример #9
0
static int check_control(struct libusb_transfer *transfer)
{
	struct aura_node *node = transfer->user_data;
	struct usb_dev_info *inf = aura_get_transportdata(node);
	int ret = 0;

	inf->cbusy = false;

	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
		if (inf->control_retry_count++ < inf->control_retry_max) {
			slog(0, SLOG_WARN, "Control transfer failed, retrying (%d/%d)",
			     inf->control_retry_count, inf->control_retry_max);
			submit_control(inf->node);
			return -EAGAIN;
		}
		slog(0, SLOG_ERROR, "usb: error completing control transfer");
		ncusb_print_libusb_transfer(transfer);
		usb_panic_and_reset_state(node);
		ret = -EIO;
	}
	return ret;
}
Пример #10
0
static void usb_close(struct aura_node *node)
{
	struct usb_dev_info *inf = aura_get_transportdata(node);
	inf->itransfer_enabled = false;
	/* Waiting for pending transfers */
	slog(4, SLOG_INFO, "usb: Waiting for transport to close...");
	usb_panic_and_reset_state(node);

	while (inf->state != AUSB_DEVICE_RESTART) 
		libusb_handle_events(inf->ctx);

	slog(4, SLOG_INFO, "usb: Cleaning up...");
	libusb_free_transfer(inf->ctransfer); 
	libusb_free_transfer(inf->itransfer); 
	free(inf->ctrlbuf);
	if (inf->handle)
		libusb_close(inf->handle); 
	libusb_exit(inf->ctx);
	if (inf->optbuf)
		free(inf->optbuf);
	free(inf);
}