Support for the HX version of the chip.

Contributed by a donor that wishes to remain anonymous.
This commit is contained in:
augustss 2005-05-11 20:25:01 +00:00
parent a83267e9a2
commit bf68872cdb

View File

@ -1,4 +1,4 @@
/* $NetBSD: uplcom.c,v 1.42 2005/05/11 10:02:28 augustss Exp $ */
/* $NetBSD: uplcom.c,v 1.43 2005/05/11 20:25:01 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.42 2005/05/11 10:02:28 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.43 2005/05/11 20:25:01 augustss Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -80,7 +80,8 @@ int uplcomdebug = 0;
#define UPLCOM_SECOND_IFACE_INDEX 1
#define UPLCOM_SET_REQUEST 0x01
#define UPLCOM_SET_CRTSCTS 0x41
#define UPLCOM_SET_CRTSCTS_0 0x41
#define UPLCOM_SET_CRTSCTS_HX 0x61
#define RSAQ_STATUS_DSR 0x02
#define RSAQ_STATUS_DCD 0x01
@ -93,6 +94,11 @@ int uplcomdebug = 0;
#define UPLCOM_FLOW_OUT_XON 0x0080
#define UPLCOM_FLOW_IN_XON 0x0100
enum pl2303_type {
UPLCOM_TYPE_0,
UPLCOM_TYPE_HX,
};
struct uplcom_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
@ -115,6 +121,8 @@ struct uplcom_softc {
u_char sc_lsr; /* Local status register */
u_char sc_msr; /* uplcom status register */
enum pl2303_type sc_type; /* PL2303 chip type */
};
/*
@ -142,6 +150,7 @@ Static int uplcom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr );
Static int uplcom_param(void *, int, struct termios *);
Static int uplcom_open(void *, int);
Static void uplcom_close(void *, int);
Static usbd_status uplcom_vendor_control_write(usbd_device_handle, u_int16_t, u_int16_t);
struct ucom_methods uplcom_methods = {
uplcom_get_status,
@ -206,6 +215,7 @@ USB_ATTACH(uplcom)
{
USB_ATTACH_START(uplcom, sc, uaa);
usbd_device_handle dev = uaa->device;
usb_device_descriptor_t *ddesc;
usb_config_descriptor_t *cdesc;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@ -238,6 +248,28 @@ USB_ATTACH(uplcom)
USB_ATTACH_ERROR_RETURN;
}
/* get the device descriptor */
ddesc = usbd_get_device_descriptor(sc->sc_udev);
if (ddesc == NULL) {
printf("%s: failed to get device descriptor\n",
USBDEVNAME(sc->sc_dev));
sc->sc_dying = 1;
USB_ATTACH_ERROR_RETURN;
}
/*
* NOTE: The Linux driver distinguishes between UPLCOM_TYPE_0
* and UPLCOM_TYPE_1 type chips by testing other fields in the
* device descriptor. As far as the uplcom driver is
* concerned, both types are identical.
* The bcdDevice field should also distinguish these versions,
* but who knows.
*/
if (UGETW(ddesc->bcdDevice) == 0x0300)
sc->sc_type = UPLCOM_TYPE_HX;
else
sc->sc_type = UPLCOM_TYPE_0;
/* get the config descriptor */
cdesc = usbd_get_config_descriptor(sc->sc_udev);
@ -468,7 +500,6 @@ uplcom_set_line_state(struct uplcom_softc *sc)
USETW(req.wLength, 0);
(void)usbd_do_request(sc->sc_udev, &req, 0);
}
void
@ -545,7 +576,10 @@ uplcom_set_crtscts(struct uplcom_softc *sc)
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UPLCOM_SET_REQUEST;
USETW(req.wValue, 0);
USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
if (sc->sc_type == UPLCOM_TYPE_HX)
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_HX);
else
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_0);
USETW(req.wLength, 0);
err = usbd_do_request(sc->sc_udev, &req, 0);
@ -647,17 +681,45 @@ uplcom_param(void *addr, int portno, struct termios *t)
return (0);
}
Static usbd_status
uplcom_vendor_control_write(usbd_device_handle dev, u_int16_t value, u_int16_t index)
{
usb_device_request_t req;
usbd_status err;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UPLCOM_SET_REQUEST;
USETW(req.wValue, value);
USETW(req.wIndex, index);
USETW(req.wLength, 0);
err = usbd_do_request(dev, &req, NULL);
if (err) {
DPRINTF(("uplcom_open: vendor write failed, err=%s (%d)\n",
usbd_errstr(err), err));
}
return err;
}
int
uplcom_open(void *addr, int portno)
{
struct uplcom_softc *sc = addr;
int err;
usbd_status err;
if (sc->sc_dying)
return (EIO);
DPRINTF(("uplcom_open: sc=%p\n", sc));
/* Some unknown device frobbing. */
if (sc->sc_type == UPLCOM_TYPE_HX)
uplcom_vendor_control_write(sc->sc_udev, 2, 0x44);
else
uplcom_vendor_control_write(sc->sc_udev, 2, 0x24);
if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number,