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"
33 haiku_init(struct libusb_context *ctx)
35 if (atomic_add(&gInitCount, 1) == 0)
36 return gUsbRoster.Start();
37 return LIBUSB_SUCCESS;
41 haiku_exit(struct libusb_context *ctx)
44 if (atomic_add(&gInitCount, -1) == 1)
49 haiku_open(struct libusb_device_handle *dev_handle)
51 USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
52 USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
54 return LIBUSB_ERROR_NO_MEM;
55 if (handle->InitCheck() == false) {
57 return LIBUSB_ERROR_NO_DEVICE;
59 *((USBDeviceHandle **)dev_handle->os_priv) = handle;
60 return LIBUSB_SUCCESS;
64 haiku_close(struct libusb_device_handle *dev_handle)
66 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
70 *((USBDeviceHandle **)dev_handle->os_priv) = NULL;
74 haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
76 USBDevice *dev = *((USBDevice **)device->os_priv);
77 memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
79 return LIBUSB_SUCCESS;
83 haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
85 USBDevice *dev = *((USBDevice **)device->os_priv);
86 const usb_configuration_descriptor *act_config = dev->ActiveConfiguration();
87 if (len > act_config->total_length)
88 return LIBUSB_ERROR_OVERFLOW;
89 memcpy(buffer, act_config, len);
91 return LIBUSB_SUCCESS;
95 haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
97 USBDevice *dev = *((USBDevice **)device->os_priv);
98 const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
100 usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
101 return LIBUSB_ERROR_INVALID_PARAM;
103 if (len > config->total_length)
104 len = config->total_length;
105 memcpy(buffer, config, len);
111 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
113 USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
114 return handle->SetConfiguration(config);
118 haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
120 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
121 return handle->ClaimInterface(interface_number);
125 haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
127 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
128 return handle->SetAltSetting(interface_number, altsetting);
132 haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
134 USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
135 haiku_set_altsetting(dev_handle,interface_number, 0);
136 return handle->ReleaseInterface(interface_number);
140 haiku_submit_transfer(struct usbi_transfer *itransfer)
142 struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
143 USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
144 return fDeviceHandle->SubmitTransfer(itransfer);
148 haiku_cancel_transfer(struct usbi_transfer *itransfer)
150 struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
151 USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
152 return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)));
156 haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
158 USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
160 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
164 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
166 USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
168 usbi_mutex_lock(&itransfer->lock);
169 if (transfer->IsCancelled()) {
171 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
172 usbi_mutex_unlock(&itransfer->lock);
173 if (itransfer->transferred < 0)
174 itransfer->transferred = 0;
175 return usbi_handle_transfer_cancellation(itransfer);
177 libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
178 if (itransfer->transferred < 0) {
179 usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
180 status = LIBUSB_TRANSFER_ERROR;
181 itransfer->transferred = 0;
184 *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
185 usbi_mutex_unlock(&itransfer->lock);
186 return usbi_handle_transfer_completion(itransfer, status);
190 haiku_clock_gettime(int clkid, struct timespec *tp)
192 if (clkid == USBI_CLOCK_REALTIME)
193 return clock_gettime(CLOCK_REALTIME, tp);
194 if (clkid == USBI_CLOCK_MONOTONIC)
195 return clock_gettime(CLOCK_MONOTONIC, tp);
196 return LIBUSB_ERROR_INVALID_PARAM;
199 const struct usbi_os_backend usbi_backend = {
200 /*.name =*/ "Haiku usbfs",
202 /*.init =*/ haiku_init,
203 /*.exit =*/ haiku_exit,
204 /*.set_option =*/ NULL,
205 /*.get_device_list =*/ NULL,
206 /*.hotplug_poll =*/ NULL,
207 /*.open =*/ haiku_open,
208 /*.close =*/ haiku_close,
209 /*.get_device_descriptor =*/ haiku_get_device_descriptor,
210 /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
211 /*.get_config_descriptor =*/ haiku_get_config_descriptor,
212 /*.get_config_descriptor_by_value =*/ NULL,
215 /*.get_configuration =*/ NULL,
216 /*.set_configuration =*/ haiku_set_configuration,
217 /*.claim_interface =*/ haiku_claim_interface,
218 /*.release_interface =*/ haiku_release_interface,
220 /*.set_interface_altsetting =*/ haiku_set_altsetting,
221 /*.clear_halt =*/ NULL,
222 /*.reset_device =*/ NULL,
224 /*.alloc_streams =*/ NULL,
225 /*.free_streams =*/ NULL,
227 /*.dev_mem_alloc =*/ NULL,
228 /*.dev_mem_free =*/ NULL,
230 /*.kernel_driver_active =*/ NULL,
231 /*.detach_kernel_driver =*/ NULL,
232 /*.attach_kernel_driver =*/ NULL,
234 /*.destroy_device =*/ NULL,
236 /*.submit_transfer =*/ haiku_submit_transfer,
237 /*.cancel_transfer =*/ haiku_cancel_transfer,
238 /*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
240 /*.handle_events =*/ NULL,
241 /*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
243 /*.clock_gettime =*/ haiku_clock_gettime,
245 #ifdef USBI_TIMERFD_AVAILABLE
246 /*.get_timerfd_clockid =*/ NULL,
249 /*.context_priv_size=*/ 0,
250 /*.device_priv_size =*/ sizeof(USBDevice *),
251 /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
252 /*.transfer_priv_size =*/ sizeof(USBTransfer *),