Beispiel #1
0
void on_msc_sent(EP_CLASS ep, void *param)
{
	USB_MSC* msc = (USB_MSC*)param;
	unsigned int block_size;
	switch (msc->state)
	{
	case MSC_STATE_DATA:
		queue_release_buffer(msc->queue, msc->current_buf);
		msc->current_buf = NULL;
		if (msc->scsi_transferred < msc->scsi_requested)
		{
			ASSERT(!queue_is_empty(msc->queue));
			msc->current_buf = queue_pull_ms(msc->queue, INFINITE);
			block_size = msc->scsi_requested - msc->scsi_transferred;
			if (block_size > msc->block_size)
				block_size = msc->block_size;
			msc->scsi_transferred += block_size;
			usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), msc->current_buf, block_size);
		}
		else
			event_set(msc->event);
		break;
	case MSC_STATE_CSW:
		msc->state = MSC_STATE_CSW_SENT;
		msc_send_csw(msc);
		break;
	case MSC_STATE_CSW_SENT:
		msc->state = MSC_STATE_CBW;
		//same buffer will be used for next cbw
		usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), msc->current_buf, CBW_SIZE);
		break;
	default:
		break;
	}
}
Beispiel #2
0
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
{
	int		ret;

	dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, len);
	if(EP_OUT(xusb) & USB_ENDPOINT_IN) {
		ERR("%s called with an input endpoint 0x%x\n", __FUNCTION__, EP_OUT(xusb));
		return -EINVAL;
	}
	ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
	if(ret < 0) {
		/*
		 * If the device was gone, it may be the
		 * result of renumeration. Ignore it.
		 */
		if(ret != -ENODEV) {
			ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
				EP_OUT(xusb), ret, usb_strerror());
			dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
			//exit(2);
		} else {
			DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb));
			xusb_close(xusb);
		}
		return ret;
	} else if(ret != len) {
		ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
			EP_OUT(xusb), ret, usb_strerror());
		dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
		return -EFAULT;
	}
	return ret;
}
Beispiel #3
0
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
{
	int		ret;
	int		retries = 0;

	dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, len);
	if (EP_OUT(xusb) & USB_ENDPOINT_IN) {
		ERR("%s called with an input endpoint 0x%x\n",
			__func__, EP_OUT(xusb));
		return -EINVAL;
	}
retry_write:
	ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
	if (ret < 0) {
		/*
		 * If the device was gone, it may be the
		 * result of renumeration. Ignore it.
		 */
		if (ret != -ENODEV) {
			ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
				EP_OUT(xusb), ret, usb_strerror());
			dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]",
				buf, len);
			/*exit(2);*/
		} else {
			DBG("bulk_write to endpoint 0x%x got ENODEV\n",
				EP_OUT(xusb));
			xusb_close(xusb);
		}
		return ret;
	}
	if (!ret) {
		ERR("bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
			EP_OUT(xusb), retries, ret);
		if (retries++ > MAX_RETRIES)
			return -EFAULT;
		usleep(100);
		goto retry_write;
	}
	if (ret != len) {
		ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
			EP_OUT(xusb), ret, usb_strerror());
		dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
		return -EFAULT;
	}
	return ret;
}
Beispiel #4
0
int xusb_claim_interface(struct xusb *xusb)
{
	const struct usb_device_descriptor	*dev_desc;
	int					ret;

	assert(xusb);
	xusb_open(xusb);	/* If it's not open yet... */
	if (usb_claim_interface(xusb->handle, xusb->interface_num) != 0) {
		ERR("usb_claim_interface %d in '%s': %s\n",
			xusb->interface_num,
			xusb->devpath_tail,
			usb_strerror());
		return 0;
	}
	xusb->is_claimed = 1;
	xusb_fill_strings(xusb);
	dev_desc = &xusb->dev->descriptor;
	DBG("ID=%04X:%04X Manufacturer=[%s] Product=[%s] "
		"SerialNumber=[%s] Interface=[%s]\n",
		dev_desc->idVendor,
		dev_desc->idProduct,
		xusb->iManufacturer,
		xusb->iProduct,
		xusb->iSerialNumber,
		xusb->iInterface);
	if (xtalk_option_use_clear_halt()) {
		DBG("Using clear_halt()\n");
		if (usb_clear_halt(xusb->handle, EP_OUT(xusb)) != 0) {
			ERR("Clearing output endpoint: %s\n", usb_strerror());
			return 0;
		}
		if (usb_clear_halt(xusb->handle, EP_IN(xusb)) != 0) {
			ERR("Clearing input endpoint: %s\n", usb_strerror());
			return 0;
		}
	}
	ret = xusb_flushread(xusb);
	if (ret < 0) {
		ERR("xusb_flushread failed: %d\n", ret);
		return 0;
	}
	return 1;
}
Beispiel #5
0
void on_storage_request_buffers(void* param, unsigned int size)
{
	USB_MSC* msc = (USB_MSC*)param;
	unsigned int block_size;
	CRITICAL_ENTER;
	msc->scsi_requested += size;
	CRITICAL_LEAVE;
	if (event_is_set(msc->event))
	{
		event_clear(msc->event);
		msc->current_buf = queue_allocate_buffer_ms(msc->queue, INFINITE);
		block_size = msc->scsi_requested - msc->scsi_transferred;
		if (block_size > msc->block_size)
			block_size = msc->block_size;
		msc->scsi_transferred += block_size;
		usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), msc->current_buf, block_size);
	}
#if (USB_MSC_DEBUG_FLOW)
	printf("USB_MSC: RX %d\n\r", size);
#endif
}
Beispiel #6
0
void on_msc_received(EP_CLASS ep, void* param)
{
	USB_MSC* msc = (USB_MSC*)param;
	unsigned int block_size;
	switch (msc->state)
	{
	case MSC_STATE_CBW:
		memcpy(&msc->cbw, msc->current_buf, CBW_SIZE);
		queue_release_buffer(msc->queue, msc->current_buf);
		msc->current_buf = NULL;
		msc->scsi_requested = 0;
		msc->scsi_transferred = 0;
		event_set(msc->event);
		break;
	case MSC_STATE_DATA:
		queue_push(msc->queue, msc->current_buf);
		msc->current_buf = NULL;
		if (msc->scsi_transferred < msc->scsi_requested)
		{
			ASSERT(!queue_is_full(msc->queue));
			msc->current_buf = queue_allocate_buffer_ms(msc->queue, INFINITE);
			block_size = msc->scsi_requested - msc->scsi_transferred;
			if (block_size > msc->block_size)
				block_size = msc->block_size;
			msc->scsi_transferred += block_size;
			usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), msc->current_buf, block_size);
		}
		else
			event_set(msc->event);
		break;
	case MSC_STATE_CSW:
		msc->state = MSC_STATE_CSW_SENT;
		msc_send_csw(msc);
		break;
	default:
		break;
	}
}
Beispiel #7
0
void usb_msc_thread(void* param)
{
	USB_MSC* msc = (USB_MSC*)param;
	for (;;)
	{
		event_wait_ms(msc->event, INFINITE);
		msc->state = MSC_STATE_DATA;
		//process received CBW
		if (msc->cbw.dCBWSignature == CBW_MAGIC && msc->cbw.bCBWCBLength <= MAX_CB_SIZE)
		{
			msc->csw_status = CSW_STATUS_OK;
#if (USB_MSC_DEBUG_FLOW)
			printf("USB_MSC: dCBWTag: %08x\n\r", msc->cbw.dCBWTag);
			printf("USB_MSC: dCBWDataTransferLength: %08x\n\r", msc->cbw.dCBWDataTransferLength);
			printf("USB_MSC: dCBWDataFlags: %02x\n\r", msc->cbw.bmCBWFlags);
			printf("USB_MSC: dCBWLUN: %02x\n\r", msc->cbw.bCBWLUN);
			printf("USB_MSC: dCBWCB:");
			int i;
			for (i = 0; i < msc->cbw.bCBWCBLength; ++i)
				printf(" %02x", msc->cbw.CBWCB[i]);
			printf(" (%d)\n\r", msc->cbw.bCBWCBLength);
#endif
			if (!scsi_cmd(msc->scsi, (char*)msc->cbw.CBWCB, msc->cbw.bCBWCBLength))
				msc->csw_status = CSW_STATUS_FAILED;
			//wait for transfer completed in any case
			event_wait_ms(msc->event, INFINITE);

		}
		//CBW invalid, phase ERROR
		else
		{
#if (USB_DEBUG_ERRORS)
			printf("Invalid CBW\n\r");
#endif
			msc->csw_status = CSW_STATUS_ERROR;
		}
		event_clear(msc->event);
		msc->state = MSC_STATE_CSW;
		//need zlp?
		if ((msc->scsi_transferred % msc->ep_size) == 0 && msc->cbw.dCBWDataTransferLength != 0 &&
			 msc->scsi_transferred < msc->cbw.dCBWDataTransferLength)
		{
			if (msc->cbw.bmCBWFlags & 0x80)
				usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), NULL, 0);
			else
				usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), NULL, 0);
	#if (USB_MSC_DEBUG_FLOW)
		if (msc->cbw.bmCBWFlags & 0x80)
			printf("USB_MSC: TX ZLP\n\r");
		else
			printf("USB_MSC: RX ZLP\n\r");
	#endif
		}
		//send csw directly
		else
		{
			if (msc->cbw.bmCBWFlags & 0x80)
				on_msc_sent(EP_IN(msc->ep_num), msc);
			else
				on_msc_received(EP_OUT(msc->ep_num), msc);
		}
	}
}