Fix issue 1) not recognizes some usb device, 2) reconnect when ffmpeg encoder error
[rtmpclient.git] / app / src / main / jni / libusb-1.0.22 / 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
33 haiku_init(struct libusb_context *ctx)
34 {
35         if (atomic_add(&gInitCount, 1) == 0)
36                 return gUsbRoster.Start();
37         return LIBUSB_SUCCESS;
38 }
39
40 static void
41 haiku_exit(struct libusb_context *ctx)
42 {
43         UNUSED(ctx);
44         if (atomic_add(&gInitCount, -1) == 1)
45                 gUsbRoster.Stop();
46 }
47
48 static int
49 haiku_open(struct libusb_device_handle *dev_handle)
50 {
51         USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
52         USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
53         if (handle == NULL)
54                 return LIBUSB_ERROR_NO_MEM;
55         if (handle->InitCheck() == false) {
56                 delete handle;
57                 return LIBUSB_ERROR_NO_DEVICE;
58         }
59         *((USBDeviceHandle **)dev_handle->os_priv) = handle;
60         return LIBUSB_SUCCESS;
61 }
62
63 static void
64 haiku_close(struct libusb_device_handle *dev_handle)
65 {
66         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
67         if (handle == NULL)
68                 return;
69         delete handle;
70         *((USBDeviceHandle **)dev_handle->os_priv) = NULL;
71 }
72
73 static int
74 haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
75 {
76         USBDevice *dev = *((USBDevice **)device->os_priv);
77         memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
78         *host_endian = 0;
79         return LIBUSB_SUCCESS;
80 }
81
82 static int
83 haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
84 {
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);
90         *host_endian = 0;
91         return LIBUSB_SUCCESS;
92 }
93
94 static int
95 haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
96 {
97         USBDevice *dev = *((USBDevice **)device->os_priv);
98         const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
99         if (config == NULL) {
100                 usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
101                 return LIBUSB_ERROR_INVALID_PARAM;
102         }
103         if (len > config->total_length)
104                 len = config->total_length;
105         memcpy(buffer, config, len);
106         *host_endian = 0;
107         return len;
108 }
109
110 static int
111 haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
112 {
113         USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
114         return handle->SetConfiguration(config);
115 }
116
117 static int
118 haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
119 {
120         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
121         return handle->ClaimInterface(interface_number);
122 }
123
124 static int
125 haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
126 {
127         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
128         return handle->SetAltSetting(interface_number, altsetting);
129 }
130
131 static int
132 haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
133 {
134         USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
135         haiku_set_altsetting(dev_handle,interface_number, 0);
136         return handle->ReleaseInterface(interface_number);
137 }
138
139 static int
140 haiku_submit_transfer(struct usbi_transfer *itransfer)
141 {
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);
145 }
146
147 static int
148 haiku_cancel_transfer(struct usbi_transfer *itransfer)
149 {
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)));
153 }
154
155 static void
156 haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
157 {
158         USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
159         delete transfer;
160         *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
161 }
162
163 static int
164 haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
165 {
166         USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
167
168         usbi_mutex_lock(&itransfer->lock);
169         if (transfer->IsCancelled()) {
170                 delete transfer;
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);
176         }
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;
182         }
183         delete transfer;
184         *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
185         usbi_mutex_unlock(&itransfer->lock);
186         return usbi_handle_transfer_completion(itransfer, status);
187 }
188
189 static int
190 haiku_clock_gettime(int clkid, struct timespec *tp)
191 {
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;
197 }
198
199 const struct usbi_os_backend usbi_backend = {
200         /*.name =*/ "Haiku usbfs",
201         /*.caps =*/ 0,
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,
213
214
215         /*.get_configuration =*/ NULL,
216         /*.set_configuration =*/ haiku_set_configuration,
217         /*.claim_interface =*/ haiku_claim_interface,
218         /*.release_interface =*/ haiku_release_interface,
219
220         /*.set_interface_altsetting =*/ haiku_set_altsetting,
221         /*.clear_halt =*/ NULL,
222         /*.reset_device =*/ NULL,
223
224         /*.alloc_streams =*/ NULL,
225         /*.free_streams =*/ NULL,
226
227         /*.dev_mem_alloc =*/ NULL,
228         /*.dev_mem_free =*/ NULL,
229
230         /*.kernel_driver_active =*/ NULL,
231         /*.detach_kernel_driver =*/ NULL,
232         /*.attach_kernel_driver =*/ NULL,
233
234         /*.destroy_device =*/ NULL,
235
236         /*.submit_transfer =*/ haiku_submit_transfer,
237         /*.cancel_transfer =*/ haiku_cancel_transfer,
238         /*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
239
240         /*.handle_events =*/ NULL,
241         /*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
242
243         /*.clock_gettime =*/ haiku_clock_gettime,
244
245 #ifdef USBI_TIMERFD_AVAILABLE
246         /*.get_timerfd_clockid =*/ NULL,
247 #endif
248
249         /*.context_priv_size=*/ 0,
250         /*.device_priv_size =*/ sizeof(USBDevice *),
251         /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
252         /*.transfer_priv_size =*/ sizeof(USBTransfer *),
253 };