source: trunk/src/ifd/sys-sunray.c @ 1137

Revision 1137, 8.4 KB checked in by alonbl, 3 years ago (diff)

Allow driver to specify events to poll

Line 
1/*
2 * Sunray specific functions
3 *
4 * Copyright (C) 2005 William Wanders <william@wanders.org>
5 *
6 * These functions need to be re-implemented for every
7 * new platform.
8 */
9
10#include "internal.h"
11#if defined(sunray)
12#include <sys/types.h>
13#include <usb.h>
14#include <sys/stat.h>
15#include <sys/ioctl.h>
16#include <sys/poll.h>
17#include <string.h>
18#include <stdio.h>
19#include <signal.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23#include <limits.h>
24
25#include <openct/driver.h>
26#define USB_READ_INTERRUPT_TIMEOUT_WORKAROUND 1
27#ifdef USB_READ_INTERRUPT_TIMEOUT_WORKAROUND
28#include <setjmp.h>
29#endif
30
31#include "usb-descriptors.h"
32
33struct usb_dev_handle *devices[128];
34
35/*
36 * Poll for presence of USB device
37 */
38int ifd_sysdep_usb_poll_presence(ifd_device_t * dev, struct pollfd *pfd)
39{
40        if (pfd->revents & POLLHUP)
41                return 0;
42        pfd->fd = dev->fd;
43        pfd->events = POLLHUP;
44        return 1;
45}
46
47int ifd_sysdep_usb_bulk(ifd_device_t * dev, int ep, void *buffer, size_t len,
48                        long timeout)
49{
50        int bytes_to_process;
51        int bytes_processed;
52        int direction =
53            (ep & IFD_USB_ENDPOINT_DIR_MASK) == IFD_USB_ENDPOINT_IN ? 1 : 0;
54
55        ct_debug("ifd_sysdep_usb_bulk: endpoint=%d direction=%d", ep,
56                 direction);
57        if (direction) {
58                if ((bytes_to_process =
59                     usb_bulk_read(devices[dev->fd], ep, buffer, len,
60                                   timeout)) < 0) {
61                        ifd_debug(6, "ifd_sysdep_usb_bulk: read failed: %s",
62                                  strerror(errno));
63                        ct_error("usb_bulk read failed: %s", strerror(errno));
64                        return IFD_ERROR_COMM_ERROR;
65                }
66                ct_debug("ifd_sysdep_usb_bulk: read %d bytes",
67                         bytes_to_process);
68                return bytes_to_process;
69        } else {
70                bytes_to_process = len;
71                if ((bytes_processed =
72                     usb_bulk_write(devices[dev->fd], ep, buffer,
73                                    bytes_to_process,
74                                    timeout)) != bytes_to_process) {
75                        ifd_debug(6, "ifd_sysdep_usb_bulk: write failed: %s",
76                                  strerror(errno));
77                        ct_error("usb_bulk write failed: %s", strerror(errno));
78                        return IFD_ERROR_COMM_ERROR;
79                }
80                ct_debug("ifd_sysdep_usb_bulk: wrote buffer[%d]=%s",
81                         bytes_processed, ct_hexdump(buffer, len));
82                return bytes_processed;
83        }
84}
85
86/*
87 * USB URB capture
88 */
89struct ifd_usb_capture {
90        int type;
91        int endpoint;
92        size_t maxpacket;
93        unsigned int interface;
94};
95
96int ifd_sysdep_usb_begin_capture(ifd_device_t * dev, int type, int ep,
97                                 size_t maxpacket, ifd_usb_capture_t ** capret)
98{
99        ifd_usb_capture_t *cap;
100
101        if (!(cap = (ifd_usb_capture_t *) calloc(1, sizeof(*cap) + maxpacket))) {
102                ct_error("out of memory");
103                return IFD_ERROR_NO_MEMORY;
104        }
105        cap->type = type;
106        cap->endpoint = ep;
107        cap->maxpacket = maxpacket;
108
109        *capret = cap;
110        return 0;
111}
112
113#ifdef USB_READ_INTERRUPT_TIMEOUT_WORKAROUND
114static jmp_buf env;
115
116void workaround_timeout(int sig)
117{
118        ifd_debug(6, "SunRay: signal_handler: sig=%d", sig);
119        switch (sig) {
120        case SIGALRM:
121                ifd_debug(6,
122                          "SunRay: workaround_timeout: sig=SIGALRM -> longjmp");
123                longjmp(env, sig);
124        default:
125                ifd_debug(6, "SunRay: workaround_timeout: exit(%d)", sig);
126                exit(sig);
127        }
128}
129#endif
130
131int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap,
132                           void *buffer, size_t len)
133{
134        return IFD_ERROR_NOT_SUPPORTED;
135}
136
137int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap,
138                           void *buffer, size_t len, long timeout)
139{
140        int bytes_to_process = 0;
141
142        ifd_debug(6, "SunRay: ifd_sysdep_usb_capture: len=%d timeout=%d", len,
143                  timeout);
144#ifdef USB_READ_INTERRUPT_TIMEOUT_WORKAROUND
145        signal(SIGALRM, workaround_timeout);
146        if (setjmp(env) != 0) {
147                ifd_debug(6,
148                          "ifd_sysdep_usb_capture: setjmp -> workaround_timeout");
149                return 0;
150        }
151        ualarm(timeout * 1000, 0);
152        timeout = 0;
153#endif
154        if ((bytes_to_process =
155             usb_interrupt_read(devices[dev->fd], cap->endpoint, buffer, len,
156                                timeout)) < 0) {
157                ualarm(0, 0);
158                ifd_debug(6,
159                          "ifd_sysdep_usb_capture: usb_interrupt_read failed: %s",
160                          strerror(errno));
161                ct_error("usb_bulk read failed: %s", strerror(errno));
162                return IFD_ERROR_COMM_ERROR;
163        }
164#ifdef USB_READ_INTERRUPT_TIMEOUT_WORKAROUND
165        ualarm(0, 0);
166#endif
167        ct_debug("ifd_sysdep_usb_capture: read buffer[%d]=%s", bytes_to_process,
168                 ct_hexdump(buffer, bytes_to_process));
169        return bytes_to_process;
170}
171
172int ifd_sysdep_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap)
173{
174        if (cap)
175                free(cap);
176        return 0;
177}
178
179/*
180 * Event fd
181 */
182int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev, short *events)
183{
184        return -1;
185}
186
187/*
188 * USB control command
189 */
190int ifd_sysdep_usb_control(ifd_device_t * dev, unsigned int requesttype,
191                           unsigned int request, unsigned int value,
192                           unsigned int index, void *data, size_t len,
193                           long timeout)
194{
195        int rc, val;
196
197        ct_debug("ifd_sysdep_usb_control: dev->fd=%d handle=0x%x", dev->fd,
198                 devices[dev->fd]);
199        if ((rc =
200             usb_control_msg(devices[dev->fd], requesttype, request, value,
201                             index, data, len, timeout)) < 0) {
202                ifd_debug(1, "usb_control_msg failed: %d", rc);
203                ct_error("usb_control_msg failed: %s(%d)",
204                         strerror(errno), errno);
205                return IFD_ERROR_COMM_ERROR;
206        }
207
208        ct_debug("ifd_sysdep_usb_control: return rc=%d", rc);
209        return rc;
210}
211
212int ifd_sysdep_usb_set_configuration(ifd_device_t * dev, int config)
213{
214        int rc;
215        if ((rc = usb_set_configuration(devices[dev->fd], config)) < 0) {
216                ifd_debug(1, "usb_set_configuration failed: %d", rc);
217                ct_error("usb_set_configuration failed: %s(%d)",
218                         strerror(errno), errno);
219                return IFD_ERROR_COMM_ERROR;
220        }
221        return 0;
222}
223
224int ifd_sysdep_usb_set_interface(ifd_device_t * dev, int ifc, int alt)
225{
226        int rc;
227
228        if ((rc = usb_set_altinterface(devices[dev->fd], alt)) < 0) {
229                ifd_debug(1, "usb_set_altinterface failed: %d", rc);
230                ct_error("usb_set_interface failed: %s(%d)",
231                         strerror(errno), errno);
232                return IFD_ERROR_COMM_ERROR;
233        }
234        return 0;
235}
236
237int ifd_sysdep_usb_claim_interface(ifd_device_t * dev, int interface)
238{
239        int rc;
240
241        ct_debug("ifd_sysdep_usb_claim_interface: interface=%d", interface);
242        if ((rc = usb_claim_interface(devices[dev->fd], interface)) < 0) {
243                ifd_debug(1, "usb_clain_interface failed: %d", rc);
244                ct_error("usb_release_interface failed: %s(%d)",
245                         strerror(errno), errno);
246                return IFD_ERROR_COMM_ERROR;
247        }
248        return 0;
249}
250
251int ifd_sysdep_usb_release_interface(ifd_device_t * dev, int interface)
252{
253        int rc;
254
255        ct_debug("ifd_sysdep_usb_release_interface: interface=%d", interface);
256        if ((rc = usb_release_interface(devices[dev->fd], interface)) < 0) {
257                ifd_debug(1, "usb_release_interface failed: %d", rc);
258                ct_error("usb_release_interface failed: %s(%d)",
259                         strerror(errno), errno);
260                return IFD_ERROR_COMM_ERROR;
261        }
262        return 0;
263}
264
265/*
266 * Open usb device
267 */
268int ifd_sysdep_usb_open(const char *name)
269{
270        struct usb_bus *bus;
271        struct usb_device *dev;
272
273        ct_debug("ifd_sysdep_usb_open: name=%s", name);
274        ct_debug("ifd_sysdep_usb_open: usb_init()");
275        usb_init();
276        ct_debug("ifd_sysdep_usb_open: usb_find_busses()");
277        usb_find_busses();
278        ct_debug("ifd_sysdep_usb_open: usb_find_devices()");
279        usb_find_devices();
280
281        ct_debug("ifd_sysdep_usb_open: walk devices");
282        for (bus = usb_busses; bus; bus = bus->next) {
283                for (dev = bus->devices; dev; dev = dev->next) {
284                        char device[PATH_MAX];
285                        int i;
286
287                        snprintf(device, sizeof(device),
288                                 "%s/usb/%s/%s",
289                                 getenv("UTDEVROOT"),
290                                 bus->dirname, dev->filename);
291                        ct_debug("ifd_sysdep_usb_open: check device=%s",
292                                 device);
293                        if (strcmp(device, name) != 0)
294                                continue;
295
296                        ct_debug
297                            ("ifd_sysdep_usb_open: found match name=%s device=%s",
298                             name, device);
299                        for (i = 0; i < 128; i++) {
300                                if (devices[i] == NULL) {
301                                        devices[i] = usb_open(dev);
302                                        ct_debug
303                                            ("ifd_sysdep_usb_open: usb_open index=%d handle=0x%x",
304                                             i, devices[i]);
305                                        return i;
306                                }
307                        }
308                }
309        }
310        return ENOENT;
311}
312
313int ifd_sysdep_usb_reset(ifd_device_t * dev)
314{
315        /* not implemented so far */
316        return -1;
317}
318
319/*
320 * Scan all usb devices to see if there is one we support
321 */
322int ifd_scan_usb(void)
323{
324        struct usb_bus *bus;
325        struct usb_device *dev;
326        ifd_devid_t id;
327
328        usb_init();
329        usb_find_busses();
330        usb_find_devices();
331
332        id.type = IFD_DEVICE_TYPE_USB;
333        id.num = 2;
334        for (bus = usb_busses; bus; bus = bus->next) {
335                for (dev = bus->devices; dev; dev = dev->next) {
336                        const char *driver;
337                        char typedev[PATH_MAX];
338
339                        id.val[0] = dev->descriptor.idVendor;
340                        id.val[1] = dev->descriptor.idProduct;
341
342                        /* FIXME: if we don't find a driver with vendor/product
343                         * then check for the interface type (ccid) and use
344                         * driver ccid... */
345
346                        if (!(driver = ifd_driver_for_id(&id)))
347                                continue;
348
349                        snprintf(typedev, sizeof(typedev),
350                                 "usb:%s/usb/%s/%s",
351                                 getenv("UTDEVROOT"),
352                                 bus->dirname, dev->filename);
353
354                        ifd_spawn_handler(driver, typedev, -1);
355                }
356        }
357        return 0;
358}
359#endif                          /* sunray */
Note: See TracBrowser for help on using the repository browser.