Merge branch 'vendor/LIBPCAP'
[dragonfly.git] / sys / bus / u4b / serial / uvisor.c
1 /*      $NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $      */
2 /*      $FreeBSD$ */
3
4 /* Also already merged from NetBSD:
5  *      $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
6  *      $NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $
7  *      $NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $
8  *      $NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $
9  *      $NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $
10  *      $NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $
11  *      $NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $
12  *      $NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $
13  *      $NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $
14  */
15
16 /*-
17  * Copyright (c) 2000 The NetBSD Foundation, Inc.
18  * All rights reserved.
19  *
20  * This code is derived from software contributed to The NetBSD Foundation
21  * by Lennart Augustsson (lennart@augustsson.net) at
22  * Carlstedt Research & Technology.
23  *
24  * Redistribution and use in source and binary forms, with or without
25  * modification, are permitted provided that the following conditions
26  * are met:
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  *
33  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
34  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
35  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
37  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43  * POSSIBILITY OF SUCH DAMAGE.
44  */
45
46 /*
47  * Handspring Visor (Palmpilot compatible PDA) driver
48  */
49
50 #include <sys/stdint.h>
51 #include <sys/param.h>
52 #include <sys/queue.h>
53 #include <sys/types.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/bus.h>
57 #include <sys/module.h>
58 #include <sys/lock.h>
59 #include <sys/condvar.h>
60 #include <sys/sysctl.h>
61 #include <sys/unistd.h>
62 #include <sys/callout.h>
63 #include <sys/malloc.h>
64 #include <sys/priv.h>
65
66 #include <bus/u4b/usb.h>
67 #include <bus/u4b/usbdi.h>
68 #include <bus/u4b/usbdi_util.h>
69 #include "usbdevs.h"
70
71 #define USB_DEBUG_VAR uvisor_debug
72 #include <bus/u4b/usb_debug.h>
73 #include <bus/u4b/usb_process.h>
74
75 #include <bus/u4b/serial/usb_serial.h>
76
77 #ifdef USB_DEBUG
78 static int uvisor_debug = 0;
79
80 static SYSCTL_NODE(_hw_usb, OID_AUTO, uvisor, CTLFLAG_RW, 0, "USB uvisor");
81 SYSCTL_INT(_hw_usb_uvisor, OID_AUTO, debug, CTLFLAG_RW,
82     &uvisor_debug, 0, "Debug level");
83 #endif
84
85 #define UVISOR_CONFIG_INDEX     0
86 #define UVISOR_IFACE_INDEX      0
87
88 /*
89  * The following buffer sizes are hardcoded due to the way the Palm
90  * firmware works. It looks like the device is not short terminating
91  * the data transferred.
92  */
93 #define UVISORIBUFSIZE         0        /* Use wMaxPacketSize */
94 #define UVISOROBUFSIZE         32       /* bytes */
95 #define UVISOROFRAMES          32       /* units */
96
97 /* From the Linux driver */
98 /*
99  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
100  * are available to be transfered to the host for the specified endpoint.
101  * Currently this is not used, and always returns 0x0001
102  */
103 #define UVISOR_REQUEST_BYTES_AVAILABLE          0x01
104
105 /*
106  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
107  * is now closing the pipe. An empty packet is sent in response.
108  */
109 #define UVISOR_CLOSE_NOTIFICATION               0x02
110
111 /*
112  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
113  * get the endpoints used by the connection.
114  */
115 #define UVISOR_GET_CONNECTION_INFORMATION       0x03
116
117 /*
118  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
119  */
120 #define UVISOR_MAX_CONN 8
121 struct uvisor_connection_info {
122         uWord   num_ports;
123         struct {
124                 uByte   port_function_id;
125                 uByte   port;
126         } __packed connections[UVISOR_MAX_CONN];
127 } __packed;
128
129 #define UVISOR_CONNECTION_INFO_SIZE 18
130
131 /* struct uvisor_connection_info.connection[x].port defines: */
132 #define UVISOR_ENDPOINT_1               0x01
133 #define UVISOR_ENDPOINT_2               0x02
134
135 /* struct uvisor_connection_info.connection[x].port_function_id defines: */
136 #define UVISOR_FUNCTION_GENERIC         0x00
137 #define UVISOR_FUNCTION_DEBUGGER        0x01
138 #define UVISOR_FUNCTION_HOTSYNC         0x02
139 #define UVISOR_FUNCTION_CONSOLE         0x03
140 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04
141
142 /*
143  * Unknown PalmOS stuff.
144  */
145 #define UVISOR_GET_PALM_INFORMATION             0x04
146 #define UVISOR_GET_PALM_INFORMATION_LEN         0x44
147
148 struct uvisor_palm_connection_info {
149         uByte   num_ports;
150         uByte   endpoint_numbers_different;
151         uWord   reserved1;
152         struct {
153                 uDWord  port_function_id;
154                 uByte   port;
155                 uByte   end_point_info;
156                 uWord   reserved;
157         } __packed connections[UVISOR_MAX_CONN];
158 } __packed;
159
160 enum {
161         UVISOR_BULK_DT_WR,
162         UVISOR_BULK_DT_RD,
163         UVISOR_N_TRANSFER,
164 };
165
166 struct uvisor_softc {
167         struct ucom_super_softc sc_super_ucom;
168         struct ucom_softc sc_ucom;
169
170         struct usb_xfer *sc_xfer[UVISOR_N_TRANSFER];
171         struct usb_device *sc_udev;
172         struct lock sc_lock;
173
174         uint16_t sc_flag;
175 #define UVISOR_FLAG_PALM4       0x0001
176 #define UVISOR_FLAG_VISOR       0x0002
177 #define UVISOR_FLAG_PALM35      0x0004
178 #define UVISOR_FLAG_SEND_NOTIFY 0x0008
179
180         uint8_t sc_iface_no;
181         uint8_t sc_iface_index;
182 };
183
184 /* prototypes */
185
186 static device_probe_t uvisor_probe;
187 static device_attach_t uvisor_attach;
188 static device_detach_t uvisor_detach;
189
190 static usb_callback_t uvisor_write_callback;
191 static usb_callback_t uvisor_read_callback;
192
193 static usb_error_t uvisor_init(struct uvisor_softc *, struct usb_device *,
194                     struct usb_config *);
195 static void     uvisor_cfg_open(struct ucom_softc *);
196 static void     uvisor_cfg_close(struct ucom_softc *);
197 static void     uvisor_start_read(struct ucom_softc *);
198 static void     uvisor_stop_read(struct ucom_softc *);
199 static void     uvisor_start_write(struct ucom_softc *);
200 static void     uvisor_stop_write(struct ucom_softc *);
201
202 static const struct usb_config uvisor_config[UVISOR_N_TRANSFER] = {
203
204         [UVISOR_BULK_DT_WR] = {
205                 .type = UE_BULK,
206                 .endpoint = UE_ADDR_ANY,
207                 .direction = UE_DIR_OUT,
208                 .bufsize = UVISOROBUFSIZE * UVISOROFRAMES,
209                 .frames = UVISOROFRAMES,
210                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
211                 .callback = &uvisor_write_callback,
212         },
213
214         [UVISOR_BULK_DT_RD] = {
215                 .type = UE_BULK,
216                 .endpoint = UE_ADDR_ANY,
217                 .direction = UE_DIR_IN,
218                 .bufsize = UVISORIBUFSIZE,
219                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
220                 .callback = &uvisor_read_callback,
221         },
222 };
223
224 static const struct ucom_callback uvisor_callback = {
225         .ucom_cfg_open = &uvisor_cfg_open,
226         .ucom_cfg_close = &uvisor_cfg_close,
227         .ucom_start_read = &uvisor_start_read,
228         .ucom_stop_read = &uvisor_stop_read,
229         .ucom_start_write = &uvisor_start_write,
230         .ucom_stop_write = &uvisor_stop_write,
231 };
232
233 static device_method_t uvisor_methods[] = {
234         DEVMETHOD(device_probe, uvisor_probe),
235         DEVMETHOD(device_attach, uvisor_attach),
236         DEVMETHOD(device_detach, uvisor_detach),
237         DEVMETHOD_END
238 };
239
240 static devclass_t uvisor_devclass;
241
242 static driver_t uvisor_driver = {
243         .name = "uvisor",
244         .methods = uvisor_methods,
245         .size = sizeof(struct uvisor_softc),
246 };
247
248 DRIVER_MODULE(uvisor, uhub, uvisor_driver, uvisor_devclass, NULL, 0);
249 MODULE_DEPEND(uvisor, ucom, 1, 1, 1);
250 MODULE_DEPEND(uvisor, usb, 1, 1, 1);
251 MODULE_VERSION(uvisor, 1);
252
253 static const STRUCT_USB_HOST_ID uvisor_devs[] = {
254 #define UVISOR_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
255         UVISOR_DEV(ACEECA, MEZ1000, UVISOR_FLAG_PALM4),
256         UVISOR_DEV(ALPHASMART, DANA_SYNC, UVISOR_FLAG_PALM4),
257         UVISOR_DEV(GARMIN, IQUE_3600, UVISOR_FLAG_PALM4),
258         UVISOR_DEV(FOSSIL, WRISTPDA, UVISOR_FLAG_PALM4),
259         UVISOR_DEV(HANDSPRING, VISOR, UVISOR_FLAG_VISOR),
260         UVISOR_DEV(HANDSPRING, TREO, UVISOR_FLAG_PALM4),
261         UVISOR_DEV(HANDSPRING, TREO600, UVISOR_FLAG_PALM4),
262         UVISOR_DEV(PALM, M500, UVISOR_FLAG_PALM4),
263         UVISOR_DEV(PALM, M505, UVISOR_FLAG_PALM4),
264         UVISOR_DEV(PALM, M515, UVISOR_FLAG_PALM4),
265         UVISOR_DEV(PALM, I705, UVISOR_FLAG_PALM4),
266         UVISOR_DEV(PALM, M125, UVISOR_FLAG_PALM4),
267         UVISOR_DEV(PALM, M130, UVISOR_FLAG_PALM4),
268         UVISOR_DEV(PALM, TUNGSTEN_Z, UVISOR_FLAG_PALM4),
269         UVISOR_DEV(PALM, TUNGSTEN_T, UVISOR_FLAG_PALM4),
270         UVISOR_DEV(PALM, ZIRE, UVISOR_FLAG_PALM4),
271         UVISOR_DEV(PALM, ZIRE31, UVISOR_FLAG_PALM4),
272         UVISOR_DEV(SAMSUNG, I500, UVISOR_FLAG_PALM4),
273         UVISOR_DEV(SONY, CLIE_40, 0),
274         UVISOR_DEV(SONY, CLIE_41, 0),
275         UVISOR_DEV(SONY, CLIE_S360, UVISOR_FLAG_PALM4),
276         UVISOR_DEV(SONY, CLIE_NX60, UVISOR_FLAG_PALM4),
277         UVISOR_DEV(SONY, CLIE_35, UVISOR_FLAG_PALM35),
278 /*  UVISOR_DEV(SONY, CLIE_25, UVISOR_FLAG_PALM4 ), */
279         UVISOR_DEV(SONY, CLIE_TJ37, UVISOR_FLAG_PALM4),
280 /*  UVISOR_DEV(SONY, CLIE_TH55, UVISOR_FLAG_PALM4 ), See PR 80935 */
281         UVISOR_DEV(TAPWAVE, ZODIAC, UVISOR_FLAG_PALM4),
282 #undef UVISOR_DEV
283 };
284
285 static int
286 uvisor_probe(device_t dev)
287 {
288         struct usb_attach_arg *uaa = device_get_ivars(dev);
289
290         if (uaa->usb_mode != USB_MODE_HOST) {
291                 return (ENXIO);
292         }
293         if (uaa->info.bConfigIndex != UVISOR_CONFIG_INDEX) {
294                 return (ENXIO);
295         }
296         if (uaa->info.bIfaceIndex != UVISOR_IFACE_INDEX) {
297                 return (ENXIO);
298         }
299         return (usbd_lookup_id_by_uaa(uvisor_devs, sizeof(uvisor_devs), uaa));
300 }
301
302 static int
303 uvisor_attach(device_t dev)
304 {
305         struct usb_attach_arg *uaa = device_get_ivars(dev);
306         struct uvisor_softc *sc = device_get_softc(dev);
307         struct usb_config uvisor_config_copy[UVISOR_N_TRANSFER];
308         int error;
309
310         DPRINTF("sc=%p\n", sc);
311         memcpy(uvisor_config_copy, uvisor_config,
312             sizeof(uvisor_config_copy));
313
314         device_set_usb_desc(dev);
315
316         lockinit(&sc->sc_lock, "uvisor", 0, LK_CANRECURSE);
317
318         sc->sc_udev = uaa->device;
319
320         /* configure the device */
321
322         sc->sc_flag = USB_GET_DRIVER_INFO(uaa);
323         sc->sc_iface_no = uaa->info.bIfaceNum;
324         sc->sc_iface_index = UVISOR_IFACE_INDEX;
325
326         error = uvisor_init(sc, uaa->device, uvisor_config_copy);
327
328         if (error) {
329                 DPRINTF("init failed, error=%s\n",
330                     usbd_errstr(error));
331                 goto detach;
332         }
333         error = usbd_transfer_setup(uaa->device, &sc->sc_iface_index,
334             sc->sc_xfer, uvisor_config_copy, UVISOR_N_TRANSFER,
335             sc, &sc->sc_lock);
336         if (error) {
337                 DPRINTF("could not allocate all pipes\n");
338                 goto detach;
339         }
340
341         error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
342             &uvisor_callback, &sc->sc_lock);
343         if (error) {
344                 DPRINTF("ucom_attach failed\n");
345                 goto detach;
346         }
347         ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
348
349         return (0);
350
351 detach:
352         uvisor_detach(dev);
353         return (ENXIO);
354 }
355
356 static int
357 uvisor_detach(device_t dev)
358 {
359         struct uvisor_softc *sc = device_get_softc(dev);
360
361         DPRINTF("sc=%p\n", sc);
362
363         ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
364         usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
365         lockuninit(&sc->sc_lock);
366
367         return (0);
368 }
369
370 static usb_error_t
371 uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config *config)
372 {
373         usb_error_t err = 0;
374         struct usb_device_request req;
375         struct uvisor_connection_info coninfo;
376         struct uvisor_palm_connection_info pconinfo;
377         uint16_t actlen;
378         uint8_t buffer[256];
379
380         if (sc->sc_flag & UVISOR_FLAG_VISOR) {
381                 DPRINTF("getting connection info\n");
382                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
383                 req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
384                 USETW(req.wValue, 0);
385                 USETW(req.wIndex, 0);
386                 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
387                 err = usbd_do_request_flags(udev, NULL,
388                     &req, &coninfo, USB_SHORT_XFER_OK,
389                     &actlen, USB_DEFAULT_TIMEOUT);
390
391                 if (err) {
392                         goto done;
393                 }
394         }
395 #ifdef USB_DEBUG
396         if (sc->sc_flag & UVISOR_FLAG_VISOR) {
397                 uint16_t i, np;
398                 const char *desc;
399
400                 np = UGETW(coninfo.num_ports);
401                 if (np > UVISOR_MAX_CONN) {
402                         np = UVISOR_MAX_CONN;
403                 }
404                 DPRINTF("Number of ports: %d\n", np);
405
406                 for (i = 0; i < np; ++i) {
407                         switch (coninfo.connections[i].port_function_id) {
408                         case UVISOR_FUNCTION_GENERIC:
409                                 desc = "Generic";
410                                 break;
411                         case UVISOR_FUNCTION_DEBUGGER:
412                                 desc = "Debugger";
413                                 break;
414                         case UVISOR_FUNCTION_HOTSYNC:
415                                 desc = "HotSync";
416                                 break;
417                         case UVISOR_FUNCTION_REMOTE_FILE_SYS:
418                                 desc = "Remote File System";
419                                 break;
420                         default:
421                                 desc = "unknown";
422                                 break;
423                         }
424                         DPRINTF("Port %d is for %s\n",
425                             coninfo.connections[i].port, desc);
426                 }
427         }
428 #endif
429
430         if (sc->sc_flag & UVISOR_FLAG_PALM4) {
431                 uint8_t port;
432
433                 /* Palm OS 4.0 Hack */
434                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
435                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
436                 USETW(req.wValue, 0);
437                 USETW(req.wIndex, 0);
438                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
439
440                 err = usbd_do_request_flags
441                     (udev, NULL, &req, &pconinfo, USB_SHORT_XFER_OK,
442                     &actlen, USB_DEFAULT_TIMEOUT);
443
444                 if (err) {
445                         goto done;
446                 }
447                 if (actlen < 12) {
448                         DPRINTF("too little data\n");
449                         err = USB_ERR_INVAL;
450                         goto done;
451                 }
452                 if (pconinfo.endpoint_numbers_different) {
453                         port = pconinfo.connections[0].end_point_info;
454                         config[0].endpoint = (port & 0xF);      /* output */
455                         config[1].endpoint = (port >> 4);       /* input */
456                 } else {
457                         port = pconinfo.connections[0].port;
458                         config[0].endpoint = (port & 0xF);      /* output */
459                         config[1].endpoint = (port & 0xF);      /* input */
460                 }
461 #if 0
462                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
463                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
464                 USETW(req.wValue, 0);
465                 USETW(req.wIndex, 0);
466                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
467                 err = usbd_do_request(udev, &req, buffer);
468                 if (err) {
469                         goto done;
470                 }
471 #endif
472         }
473         if (sc->sc_flag & UVISOR_FLAG_PALM35) {
474                 /* get the config number */
475                 DPRINTF("getting config info\n");
476                 req.bmRequestType = UT_READ;
477                 req.bRequest = UR_GET_CONFIG;
478                 USETW(req.wValue, 0);
479                 USETW(req.wIndex, 0);
480                 USETW(req.wLength, 1);
481
482                 err = usbd_do_request(udev, NULL, &req, buffer);
483                 if (err) {
484                         goto done;
485                 }
486                 /* get the interface number */
487                 DPRINTF("get the interface number\n");
488                 req.bmRequestType = UT_READ_DEVICE;
489                 req.bRequest = UR_GET_INTERFACE;
490                 USETW(req.wValue, 0);
491                 USETW(req.wIndex, 0);
492                 USETW(req.wLength, 1);
493                 err = usbd_do_request(udev, NULL, &req, buffer);
494                 if (err) {
495                         goto done;
496                 }
497         }
498 #if 0
499         uWord wAvail;
500
501         DPRINTF("getting available bytes\n");
502         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
503         req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
504         USETW(req.wValue, 0);
505         USETW(req.wIndex, 5);
506         USETW(req.wLength, sizeof(wAvail));
507         err = usbd_do_request(udev, NULL, &req, &wAvail);
508         if (err) {
509                 goto done;
510         }
511         DPRINTF("avail=%d\n", UGETW(wAvail));
512 #endif
513
514         DPRINTF("done\n");
515 done:
516         return (err);
517 }
518
519 static void
520 uvisor_cfg_open(struct ucom_softc *ucom)
521 {
522         return;
523 }
524
525 static void
526 uvisor_cfg_close(struct ucom_softc *ucom)
527 {
528         struct uvisor_softc *sc = ucom->sc_parent;
529         uint8_t buffer[UVISOR_CONNECTION_INFO_SIZE];
530         struct usb_device_request req;
531         usb_error_t err;
532
533         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;    /* XXX read? */
534         req.bRequest = UVISOR_CLOSE_NOTIFICATION;
535         USETW(req.wValue, 0);
536         USETW(req.wIndex, 0);
537         USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
538
539         err = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
540             &req, buffer, 0, 1000);
541         if (err) {
542                 DPRINTFN(0, "close notification failed, error=%s\n",
543                     usbd_errstr(err));
544         }
545 }
546
547 static void
548 uvisor_start_read(struct ucom_softc *ucom)
549 {
550         struct uvisor_softc *sc = ucom->sc_parent;
551
552         usbd_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_RD]);
553 }
554
555 static void
556 uvisor_stop_read(struct ucom_softc *ucom)
557 {
558         struct uvisor_softc *sc = ucom->sc_parent;
559
560         usbd_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_RD]);
561 }
562
563 static void
564 uvisor_start_write(struct ucom_softc *ucom)
565 {
566         struct uvisor_softc *sc = ucom->sc_parent;
567
568         usbd_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_WR]);
569 }
570
571 static void
572 uvisor_stop_write(struct ucom_softc *ucom)
573 {
574         struct uvisor_softc *sc = ucom->sc_parent;
575
576         usbd_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_WR]);
577 }
578
579 static void
580 uvisor_write_callback(struct usb_xfer *xfer, usb_error_t error)
581 {
582         struct uvisor_softc *sc = usbd_xfer_softc(xfer);
583         struct usb_page_cache *pc;
584         uint32_t actlen;
585         uint8_t x;
586
587         switch (USB_GET_STATE(xfer)) {
588         case USB_ST_SETUP:
589         case USB_ST_TRANSFERRED:
590 tr_setup:
591                 for (x = 0; x != UVISOROFRAMES; x++) {
592
593                         usbd_xfer_set_frame_offset(xfer, 
594                             x * UVISOROBUFSIZE, x);
595
596                         pc = usbd_xfer_get_frame(xfer, x);
597                         if (ucom_get_data(&sc->sc_ucom, pc, 0,
598                             UVISOROBUFSIZE, &actlen)) {
599                                 usbd_xfer_set_frame_len(xfer, x, actlen);
600                         } else {
601                                 break;
602                         }
603                 }
604                 /* check for data */
605                 if (x != 0) {
606                         usbd_xfer_set_frames(xfer, x);
607                         usbd_transfer_submit(xfer);
608                 }
609                 break;
610
611         default:                        /* Error */
612                 if (error != USB_ERR_CANCELLED) {
613                         /* try to clear stall first */
614                         usbd_xfer_set_stall(xfer);
615                         goto tr_setup;
616                 }
617                 break;
618         }
619 }
620
621 static void
622 uvisor_read_callback(struct usb_xfer *xfer, usb_error_t error)
623 {
624         struct uvisor_softc *sc = usbd_xfer_softc(xfer);
625         struct usb_page_cache *pc;
626         int actlen;
627
628         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
629
630         switch (USB_GET_STATE(xfer)) {
631         case USB_ST_TRANSFERRED:
632                 pc = usbd_xfer_get_frame(xfer, 0);
633                 ucom_put_data(&sc->sc_ucom, pc, 0, actlen);
634
635         case USB_ST_SETUP:
636 tr_setup:
637                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
638                 usbd_transfer_submit(xfer);
639                 return;
640
641         default:                        /* Error */
642                 if (error != USB_ERR_CANCELLED) {
643                         /* try to clear stall first */
644                         usbd_xfer_set_stall(xfer);
645                         goto tr_setup;
646                 }
647                 return;
648         }
649 }