xref: /aosp_15_r20/external/libusb/libusb/os/haiku_usb_raw.cpp (revision 86b64dcb59b3a0b37502ecd56e119234366a6f7e)
1 /*
2  * Haiku Backend for libusb
3  * Copyright © 2014 Akshay Jaggi <[email protected]>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <new>
25 #include <vector>
26 
27 #include "haiku_usb.h"
28 
29 USBRoster gUsbRoster;
30 int32 gInitCount = 0;
31 
32 static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
33     void *, size_t);
34 
35 static int
haiku_init(struct libusb_context * ctx)36 haiku_init(struct libusb_context *ctx)
37 {
38 	UNUSED(ctx);
39 	if (atomic_add(&gInitCount, 1) == 0)
40 		return gUsbRoster.Start();
41 	return LIBUSB_SUCCESS;
42 }
43 
44 static void
haiku_exit(struct libusb_context * ctx)45 haiku_exit(struct libusb_context *ctx)
46 {
47 	UNUSED(ctx);
48 	if (atomic_add(&gInitCount, -1) == 1)
49 		gUsbRoster.Stop();
50 }
51 
52 static int
haiku_open(struct libusb_device_handle * dev_handle)53 haiku_open(struct libusb_device_handle *dev_handle)
54 {
55 	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(dev_handle->dev));
56 	USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
57 	if (handle == NULL)
58 		return LIBUSB_ERROR_NO_MEM;
59 	if (handle->InitCheck() == false) {
60 		delete handle;
61 		return LIBUSB_ERROR_NO_DEVICE;
62 	}
63 	*((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle)) = handle;
64 	return LIBUSB_SUCCESS;
65 }
66 
67 static void
haiku_close(struct libusb_device_handle * dev_handle)68 haiku_close(struct libusb_device_handle *dev_handle)
69 {
70 	USBDeviceHandle **pHandle = (USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle);
71 	USBDeviceHandle *handle = *pHandle;
72 	if (handle == NULL)
73 		return;
74 	delete handle;
75 	*pHandle = NULL;
76 }
77 
78 static int
haiku_get_active_config_descriptor(struct libusb_device * device,void * buffer,size_t len)79 haiku_get_active_config_descriptor(struct libusb_device *device, void *buffer, size_t len)
80 {
81 	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
82 	return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len);
83 }
84 
85 static int
haiku_get_config_descriptor(struct libusb_device * device,uint8_t config_index,void * buffer,size_t len)86 haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, void *buffer, size_t len)
87 {
88 	USBDevice *dev = *((USBDevice **)usbi_get_device_priv(device));
89 	const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
90 	if (config == NULL) {
91 		usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
92 		return LIBUSB_ERROR_IO;
93 	}
94 	if (len > config->total_length) {
95 		len = config->total_length;
96 	}
97 	memcpy(buffer, config, len);
98 	return len;
99 }
100 
101 static int
haiku_set_configuration(struct libusb_device_handle * dev_handle,int config)102 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
103 {
104 	USBDeviceHandle *handle= *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
105 	if (config <= 0)
106 		return LIBUSB_ERROR_NOT_SUPPORTED;	// cannot unconfigure
107 	return handle->SetConfiguration((uint8)config);
108 }
109 
110 static int
haiku_claim_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)111 haiku_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
112 {
113 	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
114 	return handle->ClaimInterface(interface_number);
115 }
116 
117 static int
haiku_set_altsetting(struct libusb_device_handle * dev_handle,uint8_t interface_number,uint8_t altsetting)118 haiku_set_altsetting(struct libusb_device_handle *dev_handle, uint8_t interface_number, uint8_t altsetting)
119 {
120 	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
121 	return handle->SetAltSetting(interface_number, altsetting);
122 }
123 
124 static int
haiku_clear_halt(struct libusb_device_handle * dev_handle,unsigned char endpoint)125 haiku_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
126 {
127 	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
128 	return handle->ClearHalt(endpoint);
129 }
130 
131 static int
haiku_release_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)132 haiku_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
133 {
134 	USBDeviceHandle *handle = *((USBDeviceHandle **)usbi_get_device_handle_priv(dev_handle));
135 	haiku_set_altsetting(dev_handle, interface_number, 0);
136 	return handle->ReleaseInterface(interface_number);
137 }
138 
139 static int
haiku_submit_transfer(struct usbi_transfer * itransfer)140 haiku_submit_transfer(struct usbi_transfer *itransfer)
141 {
142 	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
143 	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
144 	return fDeviceHandle->SubmitTransfer(itransfer);
145 }
146 
147 static int
haiku_cancel_transfer(struct usbi_transfer * itransfer)148 haiku_cancel_transfer(struct usbi_transfer *itransfer)
149 {
150 	struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
151 	USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)usbi_get_device_handle_priv(fLibusbTransfer->dev_handle));
152 	return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_get_transfer_priv(itransfer)));
153 }
154 
155 static int
haiku_handle_transfer_completion(struct usbi_transfer * itransfer)156 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
157 {
158 	USBTransfer **pTransfer = (USBTransfer **)usbi_get_transfer_priv(itransfer);
159 	USBTransfer *transfer = *pTransfer;
160 
161 	usbi_mutex_lock(&itransfer->lock);
162 	if (transfer->IsCancelled()) {
163 		delete transfer;
164 		*pTransfer = NULL;
165 		usbi_mutex_unlock(&itransfer->lock);
166 		if (itransfer->transferred < 0)
167 			itransfer->transferred = 0;
168 		return usbi_handle_transfer_cancellation(itransfer);
169 	}
170 	libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
171 	if (itransfer->transferred < 0) {
172 		usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
173 		status = LIBUSB_TRANSFER_ERROR;
174 		itransfer->transferred = 0;
175 	}
176 	delete transfer;
177 	*pTransfer = NULL;
178 	usbi_mutex_unlock(&itransfer->lock);
179 	return usbi_handle_transfer_completion(itransfer, status);
180 }
181 
182 const struct usbi_os_backend usbi_backend = {
183 	/*.name =*/ "Haiku usbfs",
184 	/*.caps =*/ 0,
185 	/*.init =*/ haiku_init,
186 	/*.exit =*/ haiku_exit,
187 	/*.set_option =*/ NULL,
188 	/*.get_device_list =*/ NULL,
189 	/*.hotplug_poll =*/ NULL,
190 	/*.wrap_sys_device =*/ NULL,
191 	/*.open =*/ haiku_open,
192 	/*.close =*/ haiku_close,
193 
194 	/*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
195 	/*.get_config_descriptor =*/ haiku_get_config_descriptor,
196 	/*.get_config_descriptor_by_value =*/ NULL,
197 
198 	/*.get_configuration =*/ NULL,
199 	/*.set_configuration =*/ haiku_set_configuration,
200 
201 	/*.claim_interface =*/ haiku_claim_interface,
202 	/*.release_interface =*/ haiku_release_interface,
203 	/*.set_interface_altsetting =*/ haiku_set_altsetting,
204 
205 	/*.clear_halt =*/ haiku_clear_halt,
206 	/*.reset_device =*/ NULL,
207 
208 	/*.alloc_streams =*/ NULL,
209 	/*.free_streams =*/ NULL,
210 
211 	/*.dev_mem_alloc =*/ NULL,
212 	/*.dev_mem_free =*/ NULL,
213 
214 	/*.kernel_driver_active =*/ NULL,
215 	/*.detach_kernel_driver =*/ NULL,
216 	/*.attach_kernel_driver =*/ NULL,
217 
218 	/*.destroy_device =*/ NULL,
219 
220 	/*.submit_transfer =*/ haiku_submit_transfer,
221 	/*.cancel_transfer =*/ haiku_cancel_transfer,
222 	/*.clear_transfer_priv =*/ NULL,
223 
224 	/*.handle_events =*/ NULL,
225 	/*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
226 
227 	/*.context_priv_size =*/ 0,
228 	/*.device_priv_size =*/ sizeof(USBDevice *),
229 	/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
230 	/*.transfer_priv_size =*/ sizeof(USBTransfer *),
231 };
232