xref: /haiku/src/add-ons/kernel/bus_managers/usb/Transfer.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 /*
2  * Copyright 2003-2006, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		Niels S. Reedijk
8  */
9 
10 #include "usb_p.h"
11 
12 
13 Transfer::Transfer(Pipe *pipe)
14 	:	fPipe(pipe),
15 		fVector(&fData),
16 		fVectorCount(0),
17 		fBaseAddress(NULL),
18 		fFragmented(false),
19 		fActualLength(0),
20 		fCallback(NULL),
21 		fCallbackCookie(NULL),
22 		fRequestData(NULL)
23 {
24 }
25 
26 
27 Transfer::~Transfer()
28 {
29 	// we take ownership of the request data
30 	if (fRequestData)
31 		delete fRequestData;
32 
33 	if (fVector && fVector != &fData)
34 		delete[] fVector;
35 }
36 
37 
38 void
39 Transfer::SetRequestData(usb_request_data *data)
40 {
41 	fRequestData = data;
42 }
43 
44 
45 void
46 Transfer::SetData(uint8 *data, size_t dataLength)
47 {
48 	fBaseAddress = data;
49 	fData.iov_base = data;
50 	fData.iov_len = dataLength;
51 
52 	if (data && dataLength > 0)
53 		fVectorCount = 1;
54 }
55 
56 
57 void
58 Transfer::SetVector(iovec *vector, size_t vectorCount)
59 {
60 	fVector = new(std::nothrow) iovec[vectorCount];
61 	memcpy(fVector, vector, vectorCount * sizeof(iovec));
62 	fVectorCount = vectorCount;
63 	fBaseAddress = fVector[0].iov_base;
64 }
65 
66 
67 size_t
68 Transfer::VectorLength()
69 {
70 	size_t length = 0;
71 	for (size_t i = 0; i < fVectorCount; i++)
72 		length += fVector[i].iov_len;
73 
74 	// the data is to large and would overflow the allocator
75 	if (length > USB_MAX_FRAGMENT_SIZE) {
76 		length = USB_MAX_FRAGMENT_SIZE;
77 		fFragmented = true;
78 	}
79 
80 	return length;
81 }
82 
83 
84 void
85 Transfer::AdvanceByFragment(size_t actualLength)
86 {
87 	size_t length = USB_MAX_FRAGMENT_SIZE;
88 	for (size_t i = 0; i < fVectorCount; i++) {
89 		if (fVector[i].iov_len <= length) {
90 			length -= fVector[i].iov_len;
91 			fVector[i].iov_len = 0;
92 			continue;
93 		}
94 
95 		fVector[i].iov_base = (void *)((uint8 *)fVector[i].iov_base + length);
96 		fVector[i].iov_len -= length;
97 		break;
98 	}
99 
100 	fActualLength += actualLength;
101 }
102 
103 
104 void
105 Transfer::SetCallback(usb_callback_func callback, void *cookie)
106 {
107 	fCallback = callback;
108 	fCallbackCookie = cookie;
109 }
110 
111 
112 void
113 Transfer::Finished(uint32 status, size_t actualLength)
114 {
115 	if (fCallback)
116 		fCallback(fCallbackCookie, status, fBaseAddress,
117 			fActualLength + actualLength);
118 }
119