Exemple #1
0
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
{
	int	ret;
	int	retries = 0;

	if (EP_IN(xusb) & USB_ENDPOINT_OUT) {
		ERR("%s called with an output endpoint 0x%x\n",
			__func__, EP_IN(xusb));
		return -EINVAL;
	}
retry_read:
	ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
	if (ret < 0) {
		DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
			EP_IN(xusb), ret, usb_strerror());
		memset(buf, 0, len);
		return ret;
	}
	if (!ret) {
		ERR("bulk_read to endpoint 0x%x short read[%d]: (%d)\n",
			EP_IN(xusb), retries, ret);
		if (retries++ > MAX_RETRIES)
			return -EFAULT;
		usleep(100);
		goto retry_read;
	}
	dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, ret);
	return ret;
}
Exemple #2
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;
	}
}
Exemple #3
0
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
{
	int	ret;

	if(EP_IN(xusb) & USB_ENDPOINT_OUT) {
		ERR("%s called with an output endpoint 0x%x\n", __FUNCTION__, EP_IN(xusb));
		return -EINVAL;
	}
	ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
	if(ret < 0) {
		DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
			EP_IN(xusb), ret, usb_strerror());
		memset(buf, 0, len);
		return ret;
	}
	dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, ret);
	return ret;
}
Exemple #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;
}
Exemple #5
0
static inline void msc_send_csw(USB_MSC* msc)
{
	ASSERT(!queue_is_full(msc->queue));
	msc->current_buf = queue_allocate_buffer_ms(msc->queue, INFINITE);
	CSW* csw = (CSW*)msc->current_buf;
	csw->bCSWStatus = msc->csw_status;
	csw->dCSWSignature = CBW_MAGIC;
	csw->dCSWTag = msc->cbw.dCBWTag;
	csw->dCSWDataResidue = msc->scsi_transferred;
	usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), msc->current_buf, CSW_SIZE);

#if (USB_MSC_DEBUG_FLOW)
	printf("USB_MSC: TX CSW\n\r");
#endif

#if (USB_DEBUG_ERRORS)
	if (csw->bCSWStatus == CSW_STATUS_ERROR)
		printf("MSC phase error\n\r");
#endif
}
Exemple #6
0
void on_storage_buffer_filled(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_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);
	}
#if (USB_MSC_DEBUG_FLOW)
	printf("USB_MSC: TX %d\n\r", size);
#endif
}
Exemple #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);
		}
	}
}