Misc: Trim and consolidate header file usage
[platform/upstream/libusb.git] / libusb / os / haiku_usb_raw.cpp
1 /*
2  * Haiku Backend for libusb
3  * Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
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     unsigned char *, size_t, int *);
34
35 static int
36 haiku_init(struct libusb_context *ctx)
37 {
38         if (atomic_add(&gInitCount, 1) == 0)
39                 return gUsbRoster.Start();
40         return LIBUSB_SUCCESS;
41 }
42
43 static void
44 haiku_exit(struct libusb_context *ctx)
45 {
46         UNUSED(ctx);
47         if (atomic_add(&gInitCount, -1) == 1)
48                 gUsbRoster.Stop();
49 }
50
51 static int
52 haiku_open(struct libusb_device_handle *dev_handle)
53 {
54         USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
55         USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
56         if (handle == NULL)
57                 return LIBUSB_ERROR_NO_MEM;
58         if (handle->InitCheck() == false) {
59                 delete handle;
60                 return LIBUSB_ERROR_NO_DEVICE;
61         }
62         *((USBDeviceHandle **)dev_handle->os_priv) = handle;
63         return LIBUSB_SUCCESS;
64 }
65
66 static void
67 haiku_close(struct libusb_device_handle *dev_handle)
68 {
69         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
70         if (handle == NULL)
71                 return;
72         delete handle;
73         *((USBDeviceHandle **)dev_handle->os_priv) = NULL;
74 }
75
76 static int
77 haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
78 {
79         USBDevice *dev = *((USBDevice **)device->os_priv);
80         memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
81         *host_endian = 0;
82         return LIBUSB_SUCCESS;
83 }
84
85 static int
86 haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
87 {
88         USBDevice *dev = *((USBDevice **)device->os_priv);
89         return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian);
90 }
91
92 static int
93 haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
94 {
95         USBDevice *dev = *((USBDevice **)device->os_priv);
96         const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
97         if (config == NULL) {
98                 usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
99                 return LIBUSB_ERROR_INVALID_PARAM;
100         }
101         if (len > config->total_length) {
102                 len = config->total_length;
103         }
104         memcpy(buffer, config, len);
105         *host_endian = 0;
106         return len;
107 }
108
109 static int
110 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
111 {
112         USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
113         return handle->SetConfiguration(config);
114 }
115
116 static int
117 haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
118 {
119         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
120         return handle->ClaimInterface(interface_number);
121 }
122
123 static int
124 haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
125 {
126         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
127         return handle->SetAltSetting(interface_number, altsetting);
128 }
129
130 static int
131 haiku_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
132 {
133         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
134         return handle->ClearHalt(endpoint);
135 }
136
137 static int
138 haiku_reset_device(struct libusb_device_handle *dev_handle)
139 {
140         /* TODO */
141         return LIBUSB_ERROR_NOT_SUPPORTED;
142 }
143
144 static int
145 haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
146 {
147         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
148         haiku_set_altsetting(dev_handle,interface_number, 0);
149         return handle->ReleaseInterface(interface_number);
150 }
151
152 static int
153 haiku_submit_transfer(struct usbi_transfer *itransfer)
154 {
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);
158 }
159
160 static int
161 haiku_cancel_transfer(struct usbi_transfer *itransfer)
162 {
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)));
166 }
167
168 static void
169 haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
170 {
171         USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
172         delete transfer;
173         *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
174 }
175
176 static int
177 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
178 {
179         USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
180
181         usbi_mutex_lock(&itransfer->lock);
182         if (transfer->IsCancelled()) {
183                 delete transfer;
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);
189         }
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;
195         }
196         delete transfer;
197         *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
198         usbi_mutex_unlock(&itransfer->lock);
199         return usbi_handle_transfer_completion(itransfer, status);
200 }
201
202 static int
203 haiku_clock_gettime(int clkid, struct timespec *tp)
204 {
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;
210 }
211
212 const struct usbi_os_backend usbi_backend = {
213         .name = "Haiku usbfs",
214         .caps = 0,
215         .init = haiku_init,
216         .exit = haiku_exit,
217         .set_option = NULL,
218         .get_device_list = NULL,
219         .hotplug_poll = NULL,
220         .wrap_sys_device = NULL,
221         .open = haiku_open,
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,
227
228
229         .get_configuration = NULL,
230         .set_configuration = haiku_set_configuration,
231         .claim_interface = haiku_claim_interface,
232         .release_interface = haiku_release_interface,
233
234         .set_interface_altsetting = haiku_set_altsetting,
235         .clear_halt = haiku_clear_halt,
236         .reset_device = haiku_reset_device,
237
238         .alloc_streams = NULL,
239         .free_streams = NULL,
240
241         .dev_mem_alloc = NULL,
242         .dev_mem_free = NULL,
243
244         .kernel_driver_active = NULL,
245         .detach_kernel_driver = NULL,
246         .attach_kernel_driver = NULL,
247
248         .destroy_device = NULL,
249
250         .submit_transfer = haiku_submit_transfer,
251         .cancel_transfer = haiku_cancel_transfer,
252         .clear_transfer_priv = haiku_clear_transfer_priv,
253
254         .handle_events = NULL,
255         .handle_transfer_completion = haiku_handle_transfer_completion,
256
257         .clock_gettime = haiku_clock_gettime,
258
259 #ifdef USBI_TIMERFD_AVAILABLE
260         .get_timerfd_clockid = NULL,
261 #endif
262
263         .context_priv_size = 0,
264         .device_priv_size = sizeof(USBDevice *),
265         .device_handle_priv_size = sizeof(USBDeviceHandle *),
266         .transfer_priv_size = sizeof(USBTransfer *),
267 };