2 * Copyright (c) 2006-2007 Dmitry Komissaroff <dxi@mail.ru>.
3 * Copyright (c) 2007 Hasso Tepper <hasso@estpak.ee>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $DragonFly: src/sys/dev/usbmisc/uticom/uticom.c,v 1.3 2008/08/10 20:05:54 hasso Exp $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/malloc.h>
34 #include <sys/fcntl.h>
38 #include <sys/select.h>
41 #include <sys/sysctl.h>
42 #include <sys/taskqueue.h>
44 #include <bus/usb/usb.h>
45 #include <bus/usb/usbcdc.h>
46 #include <bus/usb/usbdi.h>
47 #include <bus/usb/usbdi_util.h>
48 #include <bus/usb/usbdivar.h>
49 #include <bus/usb/usb_quirks.h>
51 #include "../ucom/ucomvar.h"
53 #include "uticom_fw3410.h"
55 SYSCTL_NODE(_hw_usb, OID_AUTO, uticom, CTLFLAG_RW, 0, "USB uticom");
58 static int uticomdebug = 0;
59 SYSCTL_INT(_hw_usb_uticom, OID_AUTO, debug, CTLFLAG_RW, &uticomdebug, 0,
60 "uticom debug level");
62 #define DPRINTFN(n, x) do { if (uticomdebug > (n)) kprintf x; } while (0)
64 #define DPRINTFN(n, x)
67 #define DPRINTF(x) DPRINTFN(0, x)
69 #define UTICOM_CONFIG_INDEX 1
70 #define UTICOM_ACTIVE_INDEX 2
72 #define UTICOM_IFACE_INDEX 0
75 * These are the maximum number of bytes transferred per frame.
76 * The output buffer size cannot be increased due to the size encoding.
78 #define UTICOM_IBUFSZ 64
79 #define UTICOM_OBUFSZ 64
81 #define UTICOM_FW_BUFSZ 16284
83 #define UTICOM_INTR_INTERVAL 100 /* ms */
85 #define UTICOM_RQ_LINE 0
86 /* Used to sync data0/1-toggle on reopen bulk pipe. */
87 #define UTICOM_RQ_SOF 1
88 #define UTICOM_RQ_SON 2
90 #define UTICOM_RQ_BAUD 3
91 #define UTICOM_RQ_LCR 4
92 #define UTICOM_RQ_FCR 5
93 #define UTICOM_RQ_RTS 6
94 #define UTICOM_RQ_DTR 7
95 #define UTICOM_RQ_BREAK 8
96 #define UTICOM_RQ_CRTSCTS 9
98 #define UTICOM_BRATE_REF 923077
100 #define UTICOM_SET_DATA_BITS(x) (x - 5)
102 #define UTICOM_STOP_BITS_1 0x00
103 #define UTICOM_STOP_BITS_2 0x40
105 #define UTICOM_PARITY_NONE 0x00
106 #define UTICOM_PARITY_ODD 0x08
107 #define UTICOM_PARITY_EVEN 0x18
109 #define UTICOM_LCR_OVR 0x1
110 #define UTICOM_LCR_PTE 0x2
111 #define UTICOM_LCR_FRE 0x4
112 #define UTICOM_LCR_BRK 0x8
114 #define UTICOM_MCR_CTS 0x1
115 #define UTICOM_MCR_DSR 0x2
116 #define UTICOM_MCR_CD 0x4
117 #define UTICOM_MCR_RI 0x8
120 struct uticom_fw_header {
123 } __attribute__((packed));
126 unsigned int buf_size;
132 struct uticom_softc {
133 struct ucom_softc sc_ucom;
135 int sc_iface_number; /* interface number */
137 usbd_interface_handle sc_intr_iface; /* interrupt interface */
138 int sc_intr_number; /* interrupt number */
139 usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
140 u_char *sc_intr_buf; /* interrupt buffer */
143 u_char sc_dtr; /* current DTR state */
144 u_char sc_rts; /* current RTS state */
147 u_char sc_lsr; /* Local status register */
148 u_char sc_msr; /* uticom status register */
151 static usbd_status uticom_reset(struct uticom_softc *);
152 static usbd_status uticom_set_crtscts(struct uticom_softc *);
153 static void uticom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
155 static void uticom_set(void *, int, int, int);
156 static void uticom_dtr(struct uticom_softc *, int);
157 static void uticom_rts(struct uticom_softc *, int);
158 static void uticom_break(struct uticom_softc *, int);
159 static void uticom_get_status(void *, int, u_char *, u_char *);
161 static int uticom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr);
163 static int uticom_param(void *, int, struct termios *);
164 static int uticom_open(void *, int);
165 static void uticom_close(void *, int);
167 static int uticom_download_fw(struct uticom_softc *sc, unsigned int pipeno,
168 usbd_device_handle dev, unsigned char *firmware,
169 unsigned int firmware_size);
171 struct ucom_callback uticom_callback = {
175 NULL, /* uticom_ioctl, TODO */
182 static const struct usb_devno uticom_devs [] = {
183 { USB_DEVICE(0x0451, 0x3410) } /* TI TUSB3410 chip */
186 static device_probe_t uticom_match;
187 static device_attach_t uticom_attach;
188 static device_detach_t uticom_detach;
190 static device_method_t uticom_methods[] = {
191 DEVMETHOD(device_probe, uticom_match),
192 DEVMETHOD(device_attach, uticom_attach),
193 DEVMETHOD(device_detach, uticom_detach),
197 static driver_t uticom_driver = {
200 sizeof (struct uticom_softc)
203 DRIVER_MODULE(uticom, uhub, uticom_driver, ucom_devclass, usbd_driver_load, 0);
204 MODULE_DEPEND(uticom, usb, 1, 1, 1);
205 MODULE_DEPEND(uticom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
206 MODULE_VERSION(uticom, 1);
208 /* Sticky DSR level sysctl handling. */
209 static int uticomstickdsr = 0;
211 sysctl_hw_usb_uticom_stickdsr(SYSCTL_HANDLER_ARGS)
215 val = uticomstickdsr;
216 err = sysctl_handle_int(oidp, &val, sizeof(val), req);
217 if (err != 0 || req->newptr == NULL)
219 if (val == 0 || val == 1)
220 uticomstickdsr = val;
226 SYSCTL_PROC(_hw_usb_uticom, OID_AUTO, stickdsr, CTLTYPE_INT | CTLFLAG_RW,
227 0, sizeof(int), sysctl_hw_usb_uticom_stickdsr,
228 "I", "uticom sticky dsr level");
231 uticom_match(device_t self)
233 struct usb_attach_arg *uaa = device_get_ivars(self);
235 if (uaa->iface != NULL)
236 return (UMATCH_NONE);
238 return (usb_lookup(uticom_devs, uaa->vendor, uaa->product) != NULL ?
239 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
243 uticom_attach(device_t self)
245 struct uticom_softc *sc = device_get_softc(self);
246 struct usb_attach_arg *uaa = device_get_ivars(self);
248 usbd_device_handle dev = uaa->device;
249 struct ucom_softc *ucom;
250 usb_config_descriptor_t *cdesc;
251 usb_interface_descriptor_t *id;
252 usb_endpoint_descriptor_t *ed;
255 usb_device_descriptor_t *dd;
258 bzero(sc, sizeof (struct uticom_softc));
261 ucom->sc_iface = uaa->iface;
263 /* Initialize endpoints. */
264 ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
265 sc->sc_intr_number = -1;
266 sc->sc_intr_pipe = NULL;
268 dd = usbd_get_device_descriptor(dev);
269 DPRINTF(("%s: uticom_attach: num of configurations %d\n",
270 device_get_nameunit(self), dd->bNumConfigurations));
272 /* The device without firmware has single configuration with single
273 * bulk out interface. */
274 if (dd->bNumConfigurations > 1)
277 /* Loading firmware. */
278 DPRINTF(("%s: uticom_attach: starting loading firmware\n",
279 device_get_nameunit(self)));
281 err = usbd_set_config_index(dev, UTICOM_CONFIG_INDEX, 1);
283 device_printf(self, "failed to set configuration: %s\n",
289 /* Get the config descriptor. */
290 cdesc = usbd_get_config_descriptor(ucom->sc_udev);
293 device_printf(self, "failed to get configuration descriptor\n");
298 err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX,
301 device_printf(self, "failed to get interface: %s\n",
307 /* Find the bulk out interface used to upload firmware. */
308 id = usbd_get_interface_descriptor(ucom->sc_iface);
309 sc->sc_iface_number = id->bInterfaceNumber;
311 for (i = 0; i < id->bNumEndpoints; i++) {
312 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
315 "no endpoint descriptor for %d\n", i);
320 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
321 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
322 ucom->sc_bulkout_no = ed->bEndpointAddress;
323 DPRINTF(("%s: uticom_attach: data bulk out num: %d\n",
324 device_get_nameunit(self),
325 ed->bEndpointAddress));
328 if (ucom->sc_bulkout_no == -1) {
329 device_printf(self, "could not find data bulk out\n");
335 status = uticom_download_fw(sc, ucom->sc_bulkout_no, dev,
336 uticom_fw_3410, sizeof(uticom_fw_3410));
339 device_printf(self, "firmware download failed\n");
343 device_printf(self, "firmware download succeeded\n");
346 status = usbd_reload_device_desc(dev);
348 device_printf(self, "error reloading device descriptor\n");
354 dd = usbd_get_device_descriptor(dev);
355 DPRINTF(("%s: uticom_attach: num of configurations %d\n",
356 device_get_nameunit(self), dd->bNumConfigurations));
358 err = usbd_set_config_index(dev, UTICOM_ACTIVE_INDEX, 1);
360 device_printf(self, "failed to set configuration: %s\n",
366 /* Get the config descriptor. */
367 cdesc = usbd_get_config_descriptor(ucom->sc_udev);
369 device_printf(self, "failed to get configuration descriptor\n");
374 /* Get the interface (XXX: multiport chips are not supported yet). */
375 err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX,
378 device_printf(self, "failed to get interface: %s\n",
384 /* Find the interrupt endpoints. */
385 id = usbd_get_interface_descriptor(ucom->sc_iface);
386 sc->sc_iface_number = id->bInterfaceNumber;
388 for (i = 0; i < id->bNumEndpoints; i++) {
389 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
392 "no endpoint descriptor for %d\n", i);
397 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
398 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
399 sc->sc_intr_number = ed->bEndpointAddress;
400 sc->sc_isize = UGETW(ed->wMaxPacketSize);
404 if (sc->sc_intr_number == -1) {
405 device_printf(self, "could not find interrupt in\n");
410 /* Keep interface for interrupt. */
411 sc->sc_intr_iface = ucom->sc_iface;
413 /* Find the bulk{in,out} endpoints. */
414 id = usbd_get_interface_descriptor(ucom->sc_iface);
415 sc->sc_iface_number = id->bInterfaceNumber;
417 for (i = 0; i < id->bNumEndpoints; i++) {
418 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
421 "no endpoint descriptor for %d\n", i);
426 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
427 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
428 ucom->sc_bulkin_no = ed->bEndpointAddress;
429 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
430 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
431 ucom->sc_bulkout_no = ed->bEndpointAddress;
435 if (ucom->sc_bulkin_no == -1) {
436 device_printf(self, "could not find data bulk in\n");
441 if (ucom->sc_bulkout_no == -1) {
442 device_printf(self, "could not find data bulk out\n");
447 sc->sc_dtr = sc->sc_rts = -1;
448 ucom->sc_parent = sc;
449 ucom->sc_portno = UCOM_UNK_PORTNO;
450 ucom->sc_ibufsize = UTICOM_IBUFSZ;
451 ucom->sc_obufsize = UTICOM_OBUFSZ;
452 ucom->sc_ibufsizepad = UTICOM_IBUFSZ;
453 ucom->sc_opkthdrlen = 0;
454 ucom->sc_callback = &uticom_callback;
456 err = uticom_reset(sc);
458 device_printf(self, "reset failed: %s\n", usbd_errstr(err));
463 DPRINTF(("%s: uticom_attach: in = 0x%x, out = 0x%x, intr = 0x%x\n",
464 device_get_nameunit(self), ucom->sc_bulkin_no,
465 ucom->sc_bulkout_no, sc->sc_intr_number));
467 ucom_attach(&sc->sc_ucom);
472 uticom_detach(device_t self)
474 struct uticom_softc *sc = device_get_softc(self);
476 DPRINTF(("%s: uticom_detach: sc = %p\n",
477 device_get_nameunit(self), sc));
479 if (sc->sc_intr_pipe != NULL) {
480 usbd_abort_pipe(sc->sc_intr_pipe);
481 usbd_close_pipe(sc->sc_intr_pipe);
482 kfree(sc->sc_intr_buf, M_USBDEV);
483 sc->sc_intr_pipe = NULL;
486 sc->sc_ucom.sc_dying = 1;
487 return (ucom_detach(&sc->sc_ucom));
491 uticom_reset(struct uticom_softc *sc)
493 usb_device_request_t req;
495 device_t dev = sc->sc_ucom.sc_dev;
497 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
498 req.bRequest = UTICOM_RQ_SON;
499 USETW(req.wValue, 0);
500 USETW(req.wIndex, 0);
501 USETW(req.wLength, 0);
503 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
505 device_printf(dev, "uticom_reset: %s\n", usbd_errstr(err));
509 DPRINTF(("%s: uticom_reset: done\n", device_get_nameunit(dev)));
514 uticom_set(void *addr, int portno, int reg, int onoff)
516 struct uticom_softc *sc = addr;
520 uticom_dtr(sc, onoff);
523 uticom_rts(sc, onoff);
526 uticom_break(sc, onoff);
534 uticom_dtr(struct uticom_softc *sc, int onoff)
536 usb_device_request_t req;
538 device_t dev = sc->sc_ucom.sc_dev;
540 DPRINTF(("%s: uticom_dtr: onoff = %d\n", device_get_nameunit(dev),
543 if (sc->sc_dtr == onoff)
547 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
548 req.bRequest = UTICOM_RQ_DTR;
549 USETW(req.wValue, sc->sc_dtr ? UCDC_LINE_DTR : 0);
550 USETW(req.wIndex, 0);
551 USETW(req.wLength, 0);
553 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
555 device_printf(dev, "uticom_dtr: %s\n", usbd_errstr(err));
559 uticom_rts(struct uticom_softc *sc, int onoff)
561 usb_device_request_t req;
563 device_t dev = sc->sc_ucom.sc_dev;
565 DPRINTF(("%s: uticom_rts: onoff = %d\n", device_get_nameunit(dev),
568 if (sc->sc_rts == onoff)
571 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
572 req.bRequest = UTICOM_RQ_RTS;
573 USETW(req.wValue, sc->sc_rts ? UCDC_LINE_RTS : 0);
574 USETW(req.wIndex, 0);
575 USETW(req.wLength, 0);
577 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
579 device_printf(dev, "uticom_rts: %s\n", usbd_errstr(err));
583 uticom_break(struct uticom_softc *sc, int onoff)
585 usb_device_request_t req;
587 device_t dev = sc->sc_ucom.sc_dev;
589 DPRINTF(("%s: uticom_break: onoff = %d\n", device_get_nameunit(dev),
592 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
593 req.bRequest = UTICOM_RQ_BREAK;
594 USETW(req.wValue, onoff ? 1 : 0);
595 USETW(req.wIndex, 0);
596 USETW(req.wLength, 0);
598 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
600 device_printf(dev, "uticom_break: %s\n", usbd_errstr(err));
604 uticom_set_crtscts(struct uticom_softc *sc)
606 usb_device_request_t req;
608 device_t dev = sc->sc_ucom.sc_dev;
610 DPRINTF(("%s: uticom_set_crtscts: on\n", device_get_nameunit(dev)));
612 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
613 req.bRequest = UTICOM_RQ_CRTSCTS;
614 USETW(req.wValue, 1);
615 USETW(req.wIndex, 0);
616 USETW(req.wLength, 0);
618 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
620 device_printf(dev, "uticom_set_crtscts: %s\n",
625 return (USBD_NORMAL_COMPLETION);
629 uticom_param(void *vsc, int portno, struct termios *t)
631 struct uticom_softc *sc = (struct uticom_softc *)vsc;
632 device_t dev = sc->sc_ucom.sc_dev;
633 usb_device_request_t req;
637 DPRINTF(("%s: uticom_param\n", device_get_nameunit(dev)));
639 switch (t->c_ospeed) {
653 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
654 req.bRequest = UTICOM_RQ_BAUD;
655 USETW(req.wValue, (UTICOM_BRATE_REF / t->c_ospeed));
656 USETW(req.wIndex, 0);
657 USETW(req.wLength, 0);
659 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
661 device_printf(dev, "uticom_param: %s\n",
667 device_printf(dev, "uticom_param: unsupported baud rate %d\n",
672 switch (ISSET(t->c_cflag, CSIZE)) {
674 data = UTICOM_SET_DATA_BITS(5);
677 data = UTICOM_SET_DATA_BITS(6);
680 data = UTICOM_SET_DATA_BITS(7);
683 data = UTICOM_SET_DATA_BITS(8);
689 if (ISSET(t->c_cflag, CSTOPB))
690 data |= UTICOM_STOP_BITS_2;
692 data |= UTICOM_STOP_BITS_1;
694 if (ISSET(t->c_cflag, PARENB)) {
695 if (ISSET(t->c_cflag, PARODD))
696 data |= UTICOM_PARITY_ODD;
698 data |= UTICOM_PARITY_EVEN;
700 data |= UTICOM_PARITY_NONE;
702 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
703 req.bRequest = UTICOM_RQ_LCR;
704 USETW(req.wIndex, 0);
705 USETW(req.wLength, 0);
706 USETW(req.wValue, data);
708 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
710 device_printf(dev, "uticom_param: %s\n", usbd_errstr(err));
714 if (ISSET(t->c_cflag, CRTSCTS)) {
715 err = uticom_set_crtscts(sc);
724 uticom_open(void *addr, int portno)
726 struct uticom_softc *sc = addr;
727 device_t dev = sc->sc_ucom.sc_dev;
730 if (sc->sc_ucom.sc_dying)
733 DPRINTF(("%s: uticom_open\n", device_get_nameunit(dev)));
735 sc->sc_status = 0; /* clear status bit */
737 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
738 sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK);
739 err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number,
740 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe,
741 sc, sc->sc_intr_buf, sc->sc_isize,
742 uticom_intr, UTICOM_INTR_INTERVAL);
744 device_printf(dev, "cannot open interrupt pipe "
745 "(addr %d)\n", sc->sc_intr_number);
750 DPRINTF(("%s: uticom_open: port opened\n", device_get_nameunit(dev)));
755 uticom_close(void *addr, int portno)
757 struct uticom_softc *sc = addr;
758 device_t dev = sc->sc_ucom.sc_dev;
759 usb_device_request_t req;
762 if (sc->sc_ucom.sc_dying)
765 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
766 req.bRequest = UTICOM_RQ_SON;
767 USETW(req.wValue, 0);
768 USETW(req.wIndex, 0);
769 USETW(req.wLength, 0);
771 /* Try to reset UART part of chip. */
772 err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL);
774 device_printf(dev, "uticom_close: %s\n", usbd_errstr(err));
778 DPRINTF(("%s: uticom_close: close\n",
779 device_get_nameunit(sc->sc_ucom.sc_dev)));
781 if (sc->sc_intr_pipe != NULL) {
782 err = usbd_abort_pipe(sc->sc_intr_pipe);
784 device_printf(dev, "abort interrupt pipe failed: %s\n",
786 err = usbd_close_pipe(sc->sc_intr_pipe);
788 device_printf(dev, "close interrupt pipe failed: %s\n",
790 kfree(sc->sc_intr_buf, M_USBDEV);
791 sc->sc_intr_pipe = NULL;
796 uticom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
798 struct uticom_softc *sc = priv;
799 u_char *buf = sc->sc_intr_buf;
801 if (sc->sc_ucom.sc_dying)
804 if (status != USBD_NORMAL_COMPLETION) {
805 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
806 DPRINTF(("%s: uticom_intr: int status: %s\n",
807 device_get_nameunit(sc->sc_ucom.sc_dev),
808 usbd_errstr(status)));
812 DPRINTF(("%s: uticom_intr: abnormal status: %s\n",
813 device_get_nameunit(sc->sc_ucom.sc_dev),
814 usbd_errstr(status)));
815 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
822 DPRINTF(("%s: xfer_length = %d\n",
823 device_get_nameunit(sc->sc_ucom.sc_dev), xfer->actlen));
825 sc->sc_lsr = sc->sc_msr = 0;
829 if (buf[1] & UTICOM_MCR_CTS)
830 sc->sc_msr |= UMSR_CTS;
831 if (buf[1] & UTICOM_MCR_DSR)
832 sc->sc_msr |= UMSR_DSR;
833 if (buf[1] & UTICOM_MCR_CD)
834 sc->sc_msr |= UMSR_DCD;
835 if (buf[1] & UTICOM_MCR_RI)
836 sc->sc_msr |= UMSR_RI;
839 if (buf[0] & UTICOM_LCR_OVR)
840 sc->sc_lsr |= ULSR_OE;
841 if (buf[0] & UTICOM_LCR_PTE)
842 sc->sc_lsr |= ULSR_PE;
843 if (buf[0] & UTICOM_LCR_FRE)
844 sc->sc_lsr |= ULSR_FE;
845 if (buf[0] & UTICOM_LCR_BRK)
846 sc->sc_lsr |= ULSR_BI;
850 sc->sc_msr |= UMSR_DSR;
852 ucom_status_change(&sc->sc_ucom);
856 uticom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
859 struct uticom_softc *sc = addr;
861 DPRINTF(("uticom_get_status:\n"));
873 uticom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag,
876 struct uticom_softc *sc = addr;
879 if (sc->sc_ucom.sc_dying)
882 DPRINTF(("uticom_ioctl: cmd = 0x%08lx\n", cmd));
888 case USB_GET_CM_OVER_DATA:
889 case USB_SET_CM_OVER_DATA:
893 DPRINTF(("uticom_ioctl: unknown\n"));
902 static int uticom_download_fw(struct uticom_softc *sc, unsigned int pipeno,
903 usbd_device_handle dev, unsigned char *firmware,
904 unsigned int firmware_size)
911 usbd_xfer_handle oxfer = 0;
913 usbd_pipe_handle pipe;
914 struct uticom_fw_header *header;
916 buffer_size = UTICOM_FW_BUFSZ + sizeof(struct uticom_fw_header);
917 buffer = kmalloc(buffer_size, M_USBDEV, M_WAITOK);
919 memcpy(buffer, firmware, firmware_size);
920 memset(buffer + firmware_size, 0xff, buffer_size - firmware_size);
922 for (pos = sizeof(struct uticom_fw_header); pos < buffer_size; pos++)
923 cs = (uint8_t)(cs + buffer[pos]);
925 header = (struct uticom_fw_header*)buffer;
926 header->length = (uint16_t)(buffer_size -
927 sizeof(struct uticom_fw_header));
928 header->checkSum = cs;
930 DPRINTF(("%s: downloading firmware ...\n",
931 device_get_nameunit(sc->sc_ucom.sc_dev)));
933 err = usbd_open_pipe(sc->sc_ucom.sc_iface, pipeno, USBD_EXCLUSIVE_USE,
936 device_printf(sc->sc_ucom.sc_dev, "open bulk out error "
937 "(addr %d): %s\n", pipeno, usbd_errstr(err));
942 oxfer = usbd_alloc_xfer(dev);
948 obuf = usbd_alloc_buffer(oxfer, buffer_size);
954 memcpy(obuf, buffer, buffer_size);
956 usbd_setup_xfer(oxfer, pipe, (usbd_private_handle)sc, obuf, buffer_size,
957 USBD_NO_COPY | USBD_SYNCHRONOUS, USBD_NO_TIMEOUT, 0);
958 err = usbd_sync_transfer(oxfer);
960 if (err != USBD_NORMAL_COMPLETION)
961 device_printf(sc->sc_ucom.sc_dev, "uticom_download_fw: "
962 "error: %s\n", usbd_errstr(err));
965 usbd_free_buffer(oxfer);
966 usbd_free_xfer(oxfer);
968 usbd_abort_pipe(pipe);
969 usbd_close_pipe(pipe);
970 kfree(buffer, M_USBDEV);