xref: /haiku/src/kits/device/USBEndpoint.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2007-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  */
8 
9 #include <USBKit.h>
10 #include <usb_raw.h>
11 #include <unistd.h>
12 #include <string.h>
13 
14 
15 BUSBEndpoint::BUSBEndpoint(BUSBInterface *interface, uint32 index, int rawFD)
16 	:	fInterface(interface),
17 		fIndex(index),
18 		fRawFD(rawFD)
19 {
20 	usb_raw_command command;
21 	command.endpoint_etc.descriptor = &fDescriptor;
22 	command.endpoint_etc.config_index = fInterface->Configuration()->Index();
23 	command.endpoint_etc.interface_index = fInterface->Index();
24 	command.endpoint_etc.alternate_index = fInterface->AlternateIndex();
25 	command.endpoint_etc.endpoint_index = fIndex;
26 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command,
27 		sizeof(command)) || command.endpoint_etc.status != B_USB_RAW_STATUS_SUCCESS)
28 		memset(&fDescriptor, 0, sizeof(fDescriptor));
29 }
30 
31 
32 BUSBEndpoint::~BUSBEndpoint()
33 {
34 }
35 
36 
37 uint32
38 BUSBEndpoint::Index() const
39 {
40 	return fIndex;
41 }
42 
43 
44 const BUSBInterface *
45 BUSBEndpoint::Interface() const
46 {
47 	return fInterface;
48 }
49 
50 
51 const BUSBConfiguration *
52 BUSBEndpoint::Configuration() const
53 {
54 	return fInterface->Configuration();
55 }
56 
57 
58 const BUSBDevice *
59 BUSBEndpoint::Device() const
60 {
61 	return fInterface->Device();
62 }
63 
64 
65 bool
66 BUSBEndpoint::IsBulk() const
67 {
68 	return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK)
69 		== USB_ENDPOINT_ATTR_BULK;
70 }
71 
72 
73 bool
74 BUSBEndpoint::IsInterrupt() const
75 {
76 	return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK)
77 		== USB_ENDPOINT_ATTR_INTERRUPT;
78 }
79 
80 
81 bool
82 BUSBEndpoint::IsIsochronous() const
83 {
84 	return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK)
85 		== USB_ENDPOINT_ATTR_ISOCHRONOUS;
86 }
87 
88 
89 bool
90 BUSBEndpoint::IsControl() const
91 {
92 	return (fDescriptor.attributes & USB_ENDPOINT_ATTR_MASK)
93 		== USB_ENDPOINT_ATTR_CONTROL;
94 }
95 
96 
97 bool
98 BUSBEndpoint::IsInput() const
99 {
100 	return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
101 		== USB_ENDPOINT_ADDR_DIR_IN;
102 }
103 
104 
105 bool
106 BUSBEndpoint::IsOutput() const
107 {
108 	return (fDescriptor.endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
109 		== USB_ENDPOINT_ADDR_DIR_OUT;
110 }
111 
112 
113 uint16
114 BUSBEndpoint::MaxPacketSize() const
115 {
116 	return fDescriptor.max_packet_size;
117 }
118 
119 
120 uint8
121 BUSBEndpoint::Interval() const
122 {
123 	return fDescriptor.interval;
124 }
125 
126 
127 const usb_endpoint_descriptor *
128 BUSBEndpoint::Descriptor() const
129 {
130 	return &fDescriptor;
131 }
132 
133 
134 ssize_t
135 BUSBEndpoint::ControlTransfer(uint8 requestType, uint8 request, uint16 value,
136 	uint16 index, uint16 length, void *data) const
137 {
138 	if (length > 0 && data == NULL)
139 		return B_BAD_VALUE;
140 
141 	usb_raw_command command;
142 	command.control.request_type = requestType;
143 	command.control.request = request;
144 	command.control.value = value;
145 	command.control.index = index;
146 	command.control.length = length;
147 	command.control.data = data;
148 
149 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command,
150 		sizeof(command)) || command.control.status != B_USB_RAW_STATUS_SUCCESS)
151 		return B_ERROR;
152 
153 	return command.control.length;
154 }
155 
156 
157 ssize_t
158 BUSBEndpoint::InterruptTransfer(void *data, size_t length) const
159 {
160 	if (length > 0 && data == NULL)
161 		return B_BAD_VALUE;
162 
163 	usb_raw_command command;
164 	command.transfer.interface = fInterface->Index();
165 	command.transfer.endpoint = fIndex;
166 	command.transfer.data = data;
167 	command.transfer.length = length;
168 
169 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command,
170 		sizeof(command)) || command.transfer.status != B_USB_RAW_STATUS_SUCCESS)
171 		return B_ERROR;
172 
173 	return command.transfer.length;
174 }
175 
176 
177 ssize_t
178 BUSBEndpoint::BulkTransfer(void *data, size_t length) const
179 {
180 	if (length > 0 && data == NULL)
181 		return B_BAD_VALUE;
182 
183 	usb_raw_command command;
184 	command.transfer.interface = fInterface->Index();
185 	command.transfer.endpoint = fIndex;
186 	command.transfer.data = data;
187 	command.transfer.length = length;
188 
189 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command,
190 		sizeof(command)) || command.transfer.status != B_USB_RAW_STATUS_SUCCESS)
191 		return B_ERROR;
192 
193 	return command.transfer.length;
194 }
195 
196 
197 ssize_t
198 BUSBEndpoint::IsochronousTransfer(void *data, size_t length,
199 	usb_iso_packet_descriptor *packetDescriptors, uint32 packetCount) const
200 {
201 	if (length > 0 && data == NULL)
202 		return B_BAD_VALUE;
203 
204 	usb_raw_command command;
205 	command.isochronous.interface = fInterface->Index();
206 	command.isochronous.endpoint = fIndex;
207 	command.isochronous.data = data;
208 	command.isochronous.length = length;
209 	command.isochronous.packet_descriptors = packetDescriptors;
210 	command.isochronous.packet_count = packetCount;
211 
212 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command,
213 		sizeof(command)) || command.isochronous.status != B_USB_RAW_STATUS_SUCCESS)
214 		return B_ERROR;
215 
216 	return command.isochronous.length;
217 }
218 
219 
220 bool
221 BUSBEndpoint::IsStalled() const
222 {
223 	uint16 status = 0;
224 	Device()->ControlTransfer(USB_REQTYPE_ENDPOINT_IN,
225 		USB_REQUEST_GET_STATUS, USB_FEATURE_ENDPOINT_HALT,
226 		fDescriptor.endpoint_address, sizeof(status), &status);
227 	return status != 0;
228 }
229 
230 
231 status_t
232 BUSBEndpoint::ClearStall() const
233 {
234 	return Device()->ControlTransfer(USB_REQTYPE_ENDPOINT_OUT,
235 		USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT,
236 		fDescriptor.endpoint_address, 0, NULL);
237 }
238