summaryrefslogtreecommitdiff
path: root/minix/drivers/usb/usb_storage/urb_helper.c
blob: 80d40f89cecd0a9975a56e6680d17014ebad41b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * URB formatting related implementation
 */

#include <minix/sysutil.h>			/* panic */
#include <minix/usb.h>				/* struct usb_ctrlrequest */

#include <string.h>				/* memset */
#include <assert.h>

#include "common.h"
#include "urb_helper.h"

/*---------------------------*
 *    defined functions      *
 *---------------------------*/
/*===========================================================================*
 *    init_urb                                                               *
 *===========================================================================*/
void
init_urb(struct ddekit_usb_urb * urb, struct ddekit_usb_dev * dev,
	urb_ep_config * conf)
{
	MASS_DEBUG_DUMP;

	/* Sanity checks */
	assert(NULL != urb);
	assert(NULL != dev);
	assert((DDEKIT_USB_TRANSFER_BLK == conf->type) ||
		(DDEKIT_USB_TRANSFER_CTL == conf->type) ||
		(DDEKIT_USB_TRANSFER_INT == conf->type) ||
		(DDEKIT_USB_TRANSFER_ISO == conf->type));
	assert((conf->ep_num >= 0) && (conf->ep_num < 16));
	assert((DDEKIT_USB_IN == conf->direction) ||
		(DDEKIT_USB_OUT == conf->direction));

	/* Clear block first */
	memset(urb, 0, sizeof(*urb));

	/* Set supplied values */
	urb->dev = dev;
	urb->type = conf->type;
	urb->endpoint = conf->ep_num;
	urb->direction = conf->direction;
	urb->interval = conf->interval;
}


/*===========================================================================*
 *    attach_urb_data                                                        *
 *===========================================================================*/
void
attach_urb_data(struct ddekit_usb_urb * urb, int buf_type,
		void * buf, ddekit_uint32_t buf_len)
{
	MASS_DEBUG_DUMP;

	assert(NULL != urb);
	assert(NULL != buf);

	/* Mutual exclusion */
	if (URB_BUF_TYPE_DATA == buf_type) {
		urb->data = buf;
		urb->size = buf_len;
	} else if ( URB_BUF_TYPE_SETUP == buf_type ) {
		assert(sizeof(struct usb_ctrlrequest) == buf_len);
		urb->setup_packet = buf;
	} else
		panic("Unexpected buffer type!");
}


/*===========================================================================*
 *    blocking_urb_submit                                                    *
 *===========================================================================*/
int
blocking_urb_submit(struct ddekit_usb_urb * urb, ddekit_sem_t * sem,
		int check_len)
{
	MASS_DEBUG_DUMP;

	assert(NULL != urb);
	assert(NULL != sem);
	assert((check_len == URB_SUBMIT_CHECK_LEN) ||
		(check_len == URB_SUBMIT_ALLOW_MISMATCH));

	/* Submit and block until semaphore gets up */
	if (ddekit_usb_submit_urb(urb)) {
		MASS_MSG("Submitting DDEKit URB failed");
		return EXIT_FAILURE;
	} else {
		/* Submitting succeeded so block and wait for reply */
		ddekit_sem_down(sem);

		/* Check for DDEKit status first */
		if (urb->status) {
			MASS_MSG("Invalid DDEKit URB status");
			return EXIT_FAILURE;
		} else {
			if (URB_SUBMIT_CHECK_LEN == check_len) {
				/* Compare lengths */
				if (urb->actual_length != urb->size) {
					MASS_MSG("URB different than expected");
					return EXIT_FAILURE;
				}
			}

			return EXIT_SUCCESS;
		}
	}
}