source: libusb1/trunk/libusb/os/os2_usb.c

Last change on this file was 1938, checked in by Silvan Scherrer, 4 years ago

libusb1: adapt trunk to version 1.0.21 and made it build

File size: 17.5 KB
Line 
1/*
2 * Copyright (c) 2013 Paul Smedley <paul@smedley.id.au>
3 * Heavily influenced by openbsd_usb.c
4 * & the libusb 0.1.x port Copyright (c) 2006 Richard L Walsh
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#define INCL_DOS
22#include <os2.h>
23
24#include <config.h>
25
26#include <sys/time.h>
27#include <sys/types.h>
28
29#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35#include <sys/socket.h>
36
37#include <stdint.h>
38#include <usbcalls.h>
39
40#include "libusbi.h"
41
42struct device_priv {
43        char *devname;                          /* name of the ugen(4) node */
44        int fd;                                 /* device file descriptor */
45
46        unsigned char *cdesc;                   /* active config descriptor */
47        struct libusb_device_descriptor ddesc;  /* usb device descriptor */
48        char report[4096];
49};
50
51struct handle_priv {
52        int endpoints[USB_MAXENDPOINTS];
53};
54
55#if 1 /* directly call usbresmg */
56HFILE g_hUSBDrv;
57BOOL  g_fInit;
58#define  IOCAT_USBRES            0x000000A0  // USB Resource device control
59#define  IOCTLF_SENDCONTROLURB   0x00000036
60
61typedef struct
62{
63  ULONG  ulHandle;
64  UCHAR  bRequestType;
65  UCHAR  bRequest;
66  USHORT wValue;
67  USHORT wIndex;
68  USHORT wLength;
69  ULONG  ulTimeout; /* in milliseconds */
70  USHORT usStatus;
71} USBCALLS_CTRL_REQ, *PUSBCALLS_CTRL_REQ;
72#endif
73
74#define UE_ADDR         0x0f
75#define UE_GET_ADDR(a)  ((a) & UE_ADDR)
76
77
78/*
79 * Backend functions
80 */
81static int os2_get_device_list(struct libusb_context *,
82    struct discovered_devs **);
83static int os2_open(struct libusb_device_handle *);
84static void os2_close(struct libusb_device_handle *);
85
86static int os2_get_device_descriptor(struct libusb_device *, unsigned char *,
87    int *);
88static int os2_get_active_config_descriptor(struct libusb_device *,
89    unsigned char *, size_t, int *);
90static int os2_get_config_descriptor(struct libusb_device *, uint8_t,
91    unsigned char *, size_t, int *);
92
93static int os2_get_configuration(struct libusb_device_handle *, int *);
94static int os2_set_configuration(struct libusb_device_handle *, int);
95
96static int os2_claim_interface(struct libusb_device_handle *, int);
97static int os2_release_interface(struct libusb_device_handle *, int);
98
99static int os2_set_interface_altsetting(struct libusb_device_handle *, int,
100    int);
101static int os2_clear_halt(struct libusb_device_handle *, unsigned char);
102static int os2_reset_device(struct libusb_device_handle *);
103static void os2_destroy_device(struct libusb_device *);
104
105static int os2_submit_transfer(struct usbi_transfer *);
106static int os2_cancel_transfer(struct usbi_transfer *);
107static void os2_clear_transfer_priv(struct usbi_transfer *);
108static int os2_handle_transfer_completion(struct usbi_transfer *);
109static int os2_clock_gettime(int, struct timespec *);
110static int os2_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface);
111static int os2_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface);
112static int os2_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface);
113
114/*
115 * Private functions
116 */
117static int _errno_to_libusb(int);
118/*static int _cache_active_config_descriptor(struct libusb_device *);*/
119static int _sync_control_transfer(struct usbi_transfer *);
120static int _sync_gen_transfer(struct usbi_transfer *);
121static int _access_endpoint(struct libusb_transfer *);
122
123const struct usbi_os_backend os2_backend = {
124        "Synchronous OS/2 backend",
125        0,
126        NULL,                           /* init() */
127        NULL,                           /* exit() */
128        os2_get_device_list,
129        NULL,                           /* hotplug_poll */
130        os2_open,
131        os2_close,
132
133        os2_get_device_descriptor,
134        os2_get_active_config_descriptor,
135        os2_get_config_descriptor,
136        NULL,                           /* get_config_descriptor_by_value() */
137
138        os2_get_configuration,
139        os2_set_configuration,
140
141        os2_claim_interface,
142        os2_release_interface,
143
144        os2_set_interface_altsetting,
145        os2_clear_halt,
146        os2_reset_device,
147
148        NULL,                           /* alloc_streams */
149        NULL,                           /* free_streams */
150
151        NULL,                           /* dev_mem_alloc() */
152        NULL,                           /* dev_mem_free() */
153
154        os2_kernel_driver_active,
155        os2_detach_kernel_driver,
156        os2_attach_kernel_driver,
157
158        os2_destroy_device,
159
160        os2_submit_transfer,
161        os2_cancel_transfer,
162        os2_clear_transfer_priv,
163
164        NULL,                           /* handle_events() */
165        os2_handle_transfer_completion,
166
167        os2_clock_gettime,
168        sizeof(struct device_priv),
169        sizeof(struct handle_priv),
170        0,                              /* transfer_priv_size */
171};
172
173#define DEVPATH "/dev/"
174#define USBDEV  DEVPATH "usb"
175
176int
177os2_get_device_list(struct libusb_context * ctx,
178        struct discovered_devs **discdevs)
179{
180        APIRET    rc;
181        ULONG     cntDev;
182        ULONG     ctr;
183        ULONG     len;
184        struct libusb_device *dev;
185        struct device_priv *dpriv;
186
187        unsigned long session_id;
188        char      report[4096];
189
190        usbi_dbg("");
191
192        rc = UsbQueryNumberDevices( &cntDev);
193        if (rc) {
194                usbi_dbg( "unable to query number of USB devices - rc= %x", (int)rc);
195                return -1;
196        }
197        usbi_dbg( "%d devices detected", cntDev);
198        for (ctr = 1; ctr <= cntDev; ctr++) {
199                session_id = ctr;
200                dev = usbi_get_device_by_session_id(ctx, session_id);
201                if (dev == NULL) {
202                        dev = usbi_alloc_device(ctx, session_id);
203                        if (dev == NULL)
204                                return (LIBUSB_ERROR_NO_MEM);
205                        dev->bus_number = (uint8_t) 1;
206                        dev->device_address = ctr;
207                        dev->speed = LIBUSB_SPEED_UNKNOWN;
208
209                        /* add device_descriptor to dpriv->ddesc */
210                        len = sizeof(report);
211                        rc = UsbQueryDeviceReport( ctr, &len, report);
212                        if (rc) {
213                                usbi_dbg( "unable to query device report - device= %d  rc= %x", (int)ctr, (int)rc);
214                                return -1;
215                        }
216                        dpriv = (struct device_priv *)dev->os_priv;
217                        memcpy( &dpriv->ddesc, report, sizeof(dpriv->ddesc));
218                        memcpy( &dpriv->report, report+sizeof(dpriv->ddesc), (len - sizeof(dpriv->ddesc)));
219
220                        usbi_sanitize_device(dev);
221                }
222                if (discovered_devs_append(*discdevs, dev) == NULL)
223                        return (LIBUSB_ERROR_NO_MEM);
224        }
225  return (LIBUSB_SUCCESS);
226}
227
228int
229os2_open(struct libusb_device_handle *handle)
230{
231/* Adapted from usb_os_open() in Rich's libusb 0.1.x port */
232        struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
233        APIRET    rc;
234        int       usbhandle;
235
236        rc = UsbOpen( (PUSBHANDLE)&usbhandle,
237                (USHORT)dpriv->ddesc.idVendor,
238                (USHORT)dpriv->ddesc.idProduct,
239                (USHORT)dpriv->ddesc.bcdDevice,
240                (USHORT)USB_OPEN_FIRST_UNUSED);
241
242        if (rc) {
243                usbi_dbg( "unable to open device - id= %x/%x  rc= %x",
244                        dpriv->ddesc.idVendor, 
245                        dpriv->ddesc.idProduct, (int)rc);
246                dpriv->fd = -1;
247                return _errno_to_libusb(errno);
248        }
249
250        dpriv->fd = usbhandle;
251        usbi_dbg("open: fd %d", dpriv->fd);
252        /* set device configuration to 1st configuration */
253        rc = UsbDeviceSetConfiguration (dpriv->fd,1);
254        usbi_dbg("open, set device configuration: rc = %x, fd %d", rc, dpriv->fd);
255
256        return (LIBUSB_SUCCESS);
257}
258
259void
260os2_close(struct libusb_device_handle *handle)
261{
262/* Adapted from usb_os_close() in Rich's libusb 0.1.x port */
263        struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
264        APIRET    rc;
265
266        usbi_dbg("close: fd %d", dpriv->fd);
267
268        rc = UsbClose( (USBHANDLE)dpriv->fd);
269        if (rc) {
270                usbi_dbg( "unable to close device - id= %x/%x  handle= %x  rc= %d",
271                    dpriv->ddesc.idVendor, 
272                    dpriv->ddesc.idProduct,
273                    dpriv->fd, (int)rc);
274        }
275
276        dpriv->fd = -1;
277}
278
279int
280os2_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
281    int *host_endian)
282{
283        struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
284
285        usbi_dbg("");
286
287        memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
288
289        *host_endian = 0;
290
291        return (LIBUSB_SUCCESS);
292}
293
294int
295os2_get_active_config_descriptor(struct libusb_device *dev,
296    unsigned char *buf, size_t len, int *host_endian)
297{
298        struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
299        struct libusb_config_descriptor *ucd;
300
301        ucd = (struct libusb_config_descriptor*) (dpriv->report);
302
303        len = MIN(len, ucd->wTotalLength);
304
305        usbi_dbg("len %d", len);
306
307        memcpy(buf, dpriv->report, len); /* added 28-04-2013 */
308
309        *host_endian = 0;
310
311        return (len);
312}
313
314int
315os2_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
316    unsigned char *buf, size_t len, int *host_endian)
317{
318        struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
319
320        usbi_dbg("len %d", len);
321        memcpy(buf, dpriv->report, len);
322
323        *host_endian = 0;
324
325        return (len);
326}
327
328int
329os2_get_configuration(struct libusb_device_handle *handle, int *config)
330{
331        usbi_dbg("");
332        return (LIBUSB_ERROR_NOT_SUPPORTED);
333}
334
335int
336os2_set_configuration(struct libusb_device_handle *handle, int config)
337{
338/* based on OpenBSD code*/ 
339        struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
340        APIRET    rc;
341
342        usbi_dbg("configuration %d", config);
343
344        rc = UsbDeviceSetConfiguration( (USBHANDLE)dpriv->fd, (USHORT)config);
345        if (rc) {
346                usbi_dbg( "unable to set configuration - config= %d  rc= %x",
347                        config, (int)rc);
348                return -1;
349        }
350
351        return 0;
352}
353
354int
355os2_claim_interface(struct libusb_device_handle *handle, int iface)
356{
357/* USBRESM$ appears to handle this as part of opening the device */
358        usbi_dbg("");
359        return (LIBUSB_SUCCESS);
360}
361
362int
363os2_release_interface(struct libusb_device_handle *handle, int iface)
364{
365/* USBRESM$ appears to handle this as part of opening the device */
366        usbi_dbg("");
367        return (LIBUSB_SUCCESS);
368}
369
370int
371os2_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
372    int altsetting)
373{
374/* TO DO */
375        usbi_dbg("");
376        return (LIBUSB_SUCCESS);
377}
378
379int
380os2_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
381{
382/* TO DO */
383        usbi_dbg("");
384        return (LIBUSB_SUCCESS);
385}
386
387int
388os2_reset_device(struct libusb_device_handle *handle)
389{
390/* TO DO */
391        usbi_dbg("");
392        return (LIBUSB_ERROR_NOT_SUPPORTED);
393}
394
395void
396os2_destroy_device(struct libusb_device *dev)
397{
398/* copied from BSD */
399        struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
400
401        usbi_dbg("");
402
403        free(dpriv->cdesc);
404        free(dpriv->devname);
405}
406
407int
408os2_submit_transfer(struct usbi_transfer *itransfer)
409{
410/* Copied from BSD */
411        struct libusb_transfer *transfer;
412        struct handle_priv *hpriv;
413        int err = 0;
414
415        usbi_dbg("");
416
417        transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
418        hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
419
420        switch (transfer->type) {
421        case LIBUSB_TRANSFER_TYPE_CONTROL:
422                err = _sync_control_transfer(itransfer);
423                break;
424        case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
425                if (IS_XFEROUT(transfer)) {
426                        /* Isochronous write is not supported */
427                        err = LIBUSB_ERROR_NOT_SUPPORTED;
428                        break;
429                }
430                err = _sync_gen_transfer(itransfer);
431                break;
432        case LIBUSB_TRANSFER_TYPE_BULK:
433        case LIBUSB_TRANSFER_TYPE_INTERRUPT:
434                if (IS_XFEROUT(transfer) &&
435                    transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
436                        err = LIBUSB_ERROR_NOT_SUPPORTED;
437                        break;
438                }
439                err = _sync_gen_transfer(itransfer);
440                break;
441        case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
442                err = LIBUSB_ERROR_NOT_SUPPORTED;
443                break;
444        }
445        if (err)
446                return (err);
447
448        usbi_signal_transfer_completion(itransfer);
449
450        return (LIBUSB_SUCCESS);
451}
452
453int
454os2_cancel_transfer(struct usbi_transfer *itransfer)
455{
456/* Not supported on bsd, so we won't either */
457        usbi_dbg("");
458
459        return (LIBUSB_ERROR_NOT_SUPPORTED);
460}
461
462void
463os2_clear_transfer_priv(struct usbi_transfer *itransfer)
464{
465/* Copied from openbsd_usb.c */
466        usbi_dbg("");
467
468        /* Nothing to do */
469}
470
471int
472os2_handle_transfer_completion(struct usbi_transfer *itransfer)
473{
474        return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
475}
476
477inline int
478clock_gettime(int clock_id, struct timespec *ts)
479{
480        struct timeval tv;
481
482#if 0
483        if (clock_id != CLOCK_REALTIME) {
484                errno = EINVAL;
485                return (-1);
486        }
487#endif
488        if (gettimeofday(&tv, NULL) < 0)
489                return (-1);
490        ts->tv_sec = tv.tv_sec;
491        ts->tv_nsec = tv.tv_usec * 1000;
492        return (0);
493}
494
495int
496os2_clock_gettime(int clkid, struct timespec *tp)
497{
498        usbi_dbg("clock %d", clkid);
499
500        if (clkid == USBI_CLOCK_REALTIME)
501                return clock_gettime(CLOCK_REALTIME, tp);
502
503        if (clkid == USBI_CLOCK_MONOTONIC)
504                return clock_gettime(CLOCK_MONOTONIC, tp);
505
506        return (LIBUSB_ERROR_INVALID_PARAM);
507}
508
509int
510_errno_to_libusb(int err)
511{
512        usbi_dbg("error: %s (%d)", strerror(err), err);
513
514        switch (err) {
515        case EIO:
516                return (LIBUSB_ERROR_IO);
517        case EACCES:
518                return (LIBUSB_ERROR_ACCESS);
519        case ENOENT:
520                return (LIBUSB_ERROR_NO_DEVICE);
521        case ENOMEM:
522                return (LIBUSB_ERROR_NO_MEM);
523        }
524
525        return (LIBUSB_ERROR_OTHER);
526}
527
528int
529_sync_control_transfer(struct usbi_transfer *itransfer)
530{
531        usbi_dbg("");
532        struct libusb_transfer *transfer;
533        struct libusb_control_setup *setup;
534        struct device_priv *dpriv;
535        APIRET    rc;
536
537        transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
538        dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
539        setup = (struct libusb_control_setup *)transfer->buffer;
540
541        usbi_dbg("usbhandle = %d, type %d request %d value %d index %d length %d timeout %d",
542            dpriv->fd, setup->bmRequestType, setup->bRequest,
543            libusb_le16_to_cpu(setup->wValue),
544            libusb_le16_to_cpu(setup->wIndex),
545            libusb_le16_to_cpu(setup->wLength), transfer->timeout);
546
547        rc = UsbCtrlMessage( (USBHANDLE) dpriv->fd, (UCHAR)setup->bmRequestType,
548            (UCHAR)setup->bRequest, (USHORT)setup->wValue, (USHORT)setup->wIndex,
549            (USHORT)setup->wLength, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, (ULONG)transfer->timeout);
550
551
552        if (rc) {
553                usbi_dbg( "unable to send control message - rc= %d", (int)rc);
554                return -1;
555        }
556
557        itransfer->transferred = setup->wLength; /* not right, should be length actually transferred */
558        usbi_dbg("transferred %d", itransfer->transferred);
559        return (0);
560}
561
562int
563_access_endpoint(struct libusb_transfer *transfer)
564{
565        struct handle_priv *hpriv;
566        struct device_priv *dpriv;
567        char devnode[16];
568        int fd, endpt;
569        mode_t mode;
570
571        hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
572        dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
573
574        endpt = UE_GET_ADDR(transfer->endpoint);
575        mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
576
577        usbi_dbg("endpoint %d mode %d", endpt, mode);
578
579        if (hpriv->endpoints[endpt] < 0) {
580                /* Pick the right node given the control one */
581                snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
582                    dpriv->devname, endpt);
583
584                /* We may need to read/write to the same endpoint later. */
585                if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
586                        if ((fd = open(devnode, mode)) < 0)
587                                return (-1);
588                hpriv->endpoints[endpt] = fd;
589        }
590
591        return (hpriv->endpoints[endpt]);
592}
593
594int
595_sync_gen_transfer(struct usbi_transfer *itransfer)
596{
597        usbi_dbg("");
598        struct libusb_transfer *transfer;
599        struct device_priv *dpriv;
600        transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
601        dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
602
603        int nr = transfer->length;
604                usbi_dbg("_sync_gen_transfer nr = %d",nr);
605        APIRET    rc;
606
607        if (IS_XFERIN(transfer)) {
608        usbi_dbg("_sync_gen_transfer - UsbBulkRead");
609                rc = UsbBulkRead( (USBHANDLE) dpriv->fd, (UCHAR)transfer->endpoint, 0,
610                        (PULONG)&nr, transfer->buffer, (ULONG)transfer->timeout);
611                usbi_dbg("usbcalls UsbBulkRead with dh = %p",dpriv->fd);
612                usbi_dbg("usbcalls UsbBulkRead with bulk_in_ep = 0x%02x",transfer->endpoint);
613                usbi_dbg("usbcalls UsbBulkRead with usbcalls_timeout = %d",transfer->timeout);
614                usbi_dbg("usbcalls UsbBulkRead nr2 = %d",nr);
615                usbi_dbg("usbcalls UsbBulkRead rc = %d",rc);
616
617                if (rc == 640) {
618                        usbi_dbg("usbbulkread timeout");
619                        nr = -ETIMEDOUT;
620                }
621                // Froloff keeps changing the return code
622                if (rc && rc != USB_ERROR_LESSTRANSFERED && rc != 0x8004 && rc != 7004  && rc!=32772 && rc !=28676) {
623                        usbi_dbg( "unable to read from bulk endpoint - size= %d  nr= %d  rc= %x",
624                                transfer->length, nr, (int)rc);
625                        nr = -1;
626                }
627
628        } else {
629        usbi_dbg("_sync_gen_transfer - USBBulkWrite");
630
631                rc = UsbBulkWrite( (USBHANDLE) dpriv->fd, (UCHAR)transfer->endpoint, 0,
632                        (PULONG)nr, transfer->buffer, (ULONG)transfer->timeout);
633                usbi_dbg("usbcalls UsbBulkWrite with dh = %p",dpriv->fd);
634                usbi_dbg("usbcalls UsbBulkWrite with bulk_out_ep = 0x%02x",transfer->endpoint);
635                usbi_dbg("usbcalls UsbBulkWrite with usbcalls_timeout = %d",transfer->timeout);
636                usbi_dbg("usbcalls UsbBulkWrite rc = %d",rc);
637                if (rc) {
638                        usbi_dbg( "unable to write to bulk endpoint - size= %d  nr= %d  rc= %x",
639                                transfer->length, nr, (int)rc);
640                        nr = -1;
641                }
642        }
643        if (nr < 0)
644                return _errno_to_libusb(errno);
645        itransfer->transferred = nr;
646        usbi_dbg("itransfer->transferred = %d, nr =%d",itransfer->transferred, nr);
647        return (0);
648}
649
650// The 3 functions below are unlikely to ever get supported on OS/2
651static int os2_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
652{
653        return LIBUSB_ERROR_NOT_SUPPORTED;
654}
655
656static int os2_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
657{
658        return LIBUSB_ERROR_NOT_SUPPORTED;
659}
660
661static int os2_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
662{
663        return LIBUSB_ERROR_NOT_SUPPORTED;
664}
Note: See TracBrowser for help on using the repository browser.