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