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