2 * Haiku Backend for libusb
3 * Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
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.
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.
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
27 #include "haiku_usb.h"
32 static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
33 unsigned char *, size_t, int *);
36 haiku_init(struct libusb_context *ctx)
38 if (atomic_add(&gInitCount, 1) == 0)
39 return gUsbRoster.Start();
40 return LIBUSB_SUCCESS;
44 haiku_exit(struct libusb_context *ctx)
47 if (atomic_add(&gInitCount, -1) == 1)
52 haiku_open(struct libusb_device_handle *dev_handle)
54 USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
55 USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
57 return LIBUSB_ERROR_NO_MEM;
58 if (handle->InitCheck() == false) {
60 return LIBUSB_ERROR_NO_DEVICE;
62 *((USBDeviceHandle **)dev_handle->os_priv) = handle;
63 return LIBUSB_SUCCESS;
67 haiku_close(struct libusb_device_handle *dev_handle)
69 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
73 *((USBDeviceHandle **)dev_handle->os_priv) = NULL;
77 haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
79 USBDevice *dev = *((USBDevice **)device->os_priv);
80 memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
82 return LIBUSB_SUCCESS;
86 haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
88 USBDevice *dev = *((USBDevice **)device->os_priv);
89 return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian);
93 haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
95 USBDevice *dev = *((USBDevice **)device->os_priv);
96 const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
98 usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
99 return LIBUSB_ERROR_INVALID_PARAM;
101 if (len > config->total_length) {
102 len = config->total_length;
104 memcpy(buffer, config, len);
110 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
112 USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
113 return handle->SetConfiguration(config);
117 haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
119 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
120 return handle->ClaimInterface(interface_number);
124 haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
126 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
127 return handle->SetAltSetting(interface_number, altsetting);
131 haiku_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
133 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
134 return handle->ClearHalt(endpoint);
138 haiku_reset_device(struct libusb_device_handle *dev_handle)
141 return LIBUSB_ERROR_NOT_SUPPORTED;
145 haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
147 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
148 haiku_set_altsetting(dev_handle,interface_number, 0);
149 return handle->ReleaseInterface(interface_number);
153 haiku_submit_transfer(struct usbi_transfer *itransfer)
155 struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
156 USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
157 return fDeviceHandle->SubmitTransfer(itransfer);
161 haiku_cancel_transfer(struct usbi_transfer *itransfer)
163 struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
164 USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
165 return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)));
169 haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
171 USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
173 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
177 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
179 USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
181 usbi_mutex_lock(&itransfer->lock);
182 if (transfer->IsCancelled()) {
184 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
185 usbi_mutex_unlock(&itransfer->lock);
186 if (itransfer->transferred < 0)
187 itransfer->transferred = 0;
188 return usbi_handle_transfer_cancellation(itransfer);
190 libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
191 if (itransfer->transferred < 0) {
192 usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
193 status = LIBUSB_TRANSFER_ERROR;
194 itransfer->transferred = 0;
197 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
198 usbi_mutex_unlock(&itransfer->lock);
199 return usbi_handle_transfer_completion(itransfer, status);
203 haiku_clock_gettime(int clkid, struct timespec *tp)
205 if (clkid == USBI_CLOCK_REALTIME)
206 return clock_gettime(CLOCK_REALTIME, tp);
207 if (clkid == USBI_CLOCK_MONOTONIC)
208 return clock_gettime(CLOCK_MONOTONIC, tp);
209 return LIBUSB_ERROR_INVALID_PARAM;
212 const struct usbi_os_backend usbi_backend = {
213 .name = "Haiku usbfs",
218 .get_device_list = NULL,
219 .hotplug_poll = NULL,
220 .wrap_sys_device = NULL,
222 .close = haiku_close,
223 .get_device_descriptor = haiku_get_device_descriptor,
224 .get_active_config_descriptor = haiku_get_active_config_descriptor,
225 .get_config_descriptor = haiku_get_config_descriptor,
226 .get_config_descriptor_by_value = NULL,
229 .get_configuration = NULL,
230 .set_configuration = haiku_set_configuration,
231 .claim_interface = haiku_claim_interface,
232 .release_interface = haiku_release_interface,
234 .set_interface_altsetting = haiku_set_altsetting,
235 .clear_halt = haiku_clear_halt,
236 .reset_device = haiku_reset_device,
238 .alloc_streams = NULL,
239 .free_streams = NULL,
241 .dev_mem_alloc = NULL,
242 .dev_mem_free = NULL,
244 .kernel_driver_active = NULL,
245 .detach_kernel_driver = NULL,
246 .attach_kernel_driver = NULL,
248 .destroy_device = NULL,
250 .submit_transfer = haiku_submit_transfer,
251 .cancel_transfer = haiku_cancel_transfer,
252 .clear_transfer_priv = haiku_clear_transfer_priv,
254 .handle_events = NULL,
255 .handle_transfer_completion = haiku_handle_transfer_completion,
257 .clock_gettime = haiku_clock_gettime,
259 #ifdef USBI_TIMERFD_AVAILABLE
260 .get_timerfd_clockid = NULL,
263 .context_priv_size = 0,
264 .device_priv_size = sizeof(USBDevice *),
265 .device_handle_priv_size = sizeof(USBDeviceHandle *),
266 .transfer_priv_size = sizeof(USBTransfer *),