Ejemplo n.º 1
0
int
umodem_match(struct device *parent, void *match, void *aux)
{
    struct usb_attach_arg *uaa = aux;
    usb_interface_descriptor_t *id;
    usb_device_descriptor_t *dd;
    int data_iface_idx, cm_cap, acm_cap, ret = UMATCH_NONE;

    if (uaa->iface == NULL)
        return (ret);

    id = usbd_get_interface_descriptor(uaa->iface);
    dd = usbd_get_device_descriptor(uaa->device);
    if (id == NULL || dd == NULL)
        return (ret);

    ret = UMATCH_NONE;

    /* protocol of 0 so won't match the test below */
    if (UGETW(dd->idVendor) == USB_VENDOR_ATMEL &&
            UGETW(dd->idProduct) == USB_PRODUCT_ATMEL_AT91_CDC_ACM)
        ret = UMATCH_VENDOR_PRODUCT;

    if (UGETW(dd->idVendor) == USB_VENDOR_KYOCERA &&
            UGETW(dd->idProduct) == USB_PRODUCT_KYOCERA_AHK3001V &&
            id->bInterfaceNumber == 0)
        ret = UMATCH_VENDOR_PRODUCT;

    if (ret == UMATCH_NONE &&
            id->bInterfaceClass == UICLASS_CDC &&
            id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL &&
            id->bInterfaceProtocol == UIPROTO_CDC_AT)
        ret = UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;

    if (ret == UMATCH_NONE)
        return (ret);

    /* umodem doesn't support devices without a data iface */
    umodem_get_caps(uaa, id->bInterfaceNumber, &data_iface_idx,
                    &cm_cap, &acm_cap);
    if (data_iface_idx == -1)
        ret = UMATCH_NONE;

    return (ret);
}
Ejemplo n.º 2
0
int
umodem_match(device_t parent, cfdata_t match, void *aux)
{
	struct usbif_attach_arg *uiaa = aux;
	usb_interface_descriptor_t *id;
	int cm, acm;

	if (uiaa->uiaa_class != UICLASS_CDC ||
	    uiaa->uiaa_subclass != UISUBCLASS_ABSTRACT_CONTROL_MODEL ||
	    !(uiaa->uiaa_proto == UIPROTO_CDC_NOCLASS || uiaa->uiaa_proto == UIPROTO_CDC_AT))
		return UMATCH_NONE;

	id = usbd_get_interface_descriptor(uiaa->uiaa_iface);
	if (umodem_get_caps(uiaa->uiaa_device, &cm, &acm, id) == -1)
		return UMATCH_NONE;

	return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
}
Ejemplo n.º 3
0
static int
umodem_match(device_t self)
{
	struct usb_attach_arg *uaa = device_get_ivars(self);
	usb_interface_descriptor_t *id;
	int cm, acm;

	if (uaa->iface == NULL)
		return (UMATCH_NONE);

	id = usbd_get_interface_descriptor(uaa->iface);
	if (id == NULL ||
	    id->bInterfaceClass != UICLASS_CDC ||
	    id->bInterfaceSubClass != UISUBCLASS_ABSTRACT_CONTROL_MODEL ||
	    id->bInterfaceProtocol != UIPROTO_CDC_AT)
		return (UMATCH_NONE);

	if (umodem_get_caps(uaa->device, &cm, &acm, id) == -1)
		return (UMATCH_NONE);

	return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
Ejemplo n.º 4
0
static int
umodem_attach(device_t self)
{
	struct umodem_softc *sc = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);
	usbd_device_handle dev = uaa->device;
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	const char *devname;
	usbd_status err;
	int data_ifcno;
	int i;
	struct ucom_softc *ucom;

	ucom = &sc->sc_ucom;
	ucom->sc_dev = self;
	sc->sc_dev = self;
	ucom->sc_udev = dev;
	ucom->sc_iface = uaa->iface;

	sc->sc_udev = dev;
	sc->sc_ctl_iface = uaa->iface;

	devname = device_get_nameunit(sc->sc_dev);
	/* XXX ? use something else ? XXX */
	id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
	sc->sc_ctl_iface_no = id->bInterfaceNumber;

	sc->sc_data_iface_no = data_ifcno =
		umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap, id);

	if (data_ifcno == -1) {
		kprintf("%s: no pointer to data interface\n", devname);
		goto bad;
	}

	kprintf("%s: data interface %d, has %sCM over data, has %sbreak\n",
	       devname, data_ifcno,
	       sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ",
	       sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no ");

	/* Get the data interface too. */
	for (i = 0; i < uaa->nifaces; i++) {
		if (uaa->ifaces[i] != NULL) {
			id = usbd_get_interface_descriptor(uaa->ifaces[i]);
			if (id != NULL && id->bInterfaceNumber == data_ifcno) {
				sc->sc_data_iface = uaa->ifaces[i];
				uaa->ifaces[i] = NULL;
			}
		}
	}
	if (sc->sc_data_iface == NULL) {
		kprintf("%s: no data interface\n", devname);
		goto bad;
	}
	ucom->sc_iface = sc->sc_data_iface;

	/*
	 * Find the bulk endpoints.
	 * Iterate over all endpoints in the data interface and take note.
	 */
	ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;

	id = usbd_get_interface_descriptor(sc->sc_data_iface);
	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
		if (ed == NULL) {
			kprintf("%s: no endpoint descriptor for %d\n", devname,
			    i);
			goto bad;
		}
		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			ucom->sc_bulkin_no = ed->bEndpointAddress;
		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			ucom->sc_bulkout_no = ed->bEndpointAddress;
		}
	}

	if (ucom->sc_bulkin_no == -1) {
		kprintf("%s: Could not find data bulk in\n", devname);
		goto bad;
	}
	if (ucom->sc_bulkout_no == -1) {
		kprintf("%s: Could not find data bulk out\n", devname);
		goto bad;
	}

	if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_ASSUME_CM_OVER_DATA) {
		DPRINTF(("Quirk says to assume CM over data\n"));
		sc->sc_cm_over_data = 1;
	} else {
		if (sc->sc_cm_cap & USB_CDC_CM_OVER_DATA) {
			if (sc->sc_acm_cap & USB_CDC_ACM_HAS_FEATURE)
				err = umodem_set_comm_feature(sc,
				    UCDC_ABSTRACT_STATE, UCDC_DATA_MULTIPLEXED);
			else
				err = 0;
			if (err) {
				kprintf("%s: could not set data multiplex mode\n",
				    devname);
				goto bad;
			}
			sc->sc_cm_over_data = 1;
		}
	}

	/*
	 * The standard allows for notification messages (to indicate things
	 * like a modem hangup) to come in via an interrupt endpoint
	 * off of the control interface.  Iterate over the endpoints on
	 * the control interface and see if there are any interrupt
	 * endpoints; if there are, then register it.
	 */

	sc->sc_ctl_notify = -1;
	sc->sc_notify_pipe = NULL;

	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
		if (ed == NULL)
			continue;

		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
			kprintf("%s: status change notification available\n",
			    devname);
			sc->sc_ctl_notify = ed->bEndpointAddress;
		}
	}

	sc->sc_dtr = -1;

	ucom->sc_parent = sc;
	ucom->sc_portno = UCOM_UNK_PORTNO;
	/* bulkin, bulkout set above */
	ucom->sc_ibufsize = UMODEMIBUFSIZE;
	ucom->sc_obufsize = UMODEMOBUFSIZE;
	ucom->sc_ibufsizepad = UMODEMIBUFSIZE;
	ucom->sc_opkthdrlen = 0;
	ucom->sc_callback = &umodem_callback;

	ucom_attach(&sc->sc_ucom);

	return 0;

 bad:
	ucom->sc_dying = 1;
	return ENXIO;
}
Ejemplo n.º 5
0
void
umodem_attach(struct device *parent, struct device *self, void *aux)
{
    struct umodem_softc *sc = (struct umodem_softc *)self;
    struct usb_attach_arg *uaa = aux;
    struct usbd_device *dev = uaa->device;
    usb_interface_descriptor_t *id;
    usb_endpoint_descriptor_t *ed;
    usbd_status err;
    int data_iface_idx = -1;
    int i;
    struct ucom_attach_args uca;

    sc->sc_udev = dev;
    sc->sc_ctl_iface = uaa->iface;

    id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
    //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname,
    //    id->bInterfaceClass, id->bInterfaceSubClass);
    sc->sc_ctl_iface_no = id->bInterfaceNumber;

    /* Get the capabilities. */
    umodem_get_caps(uaa, id->bInterfaceNumber, &data_iface_idx,
                    &sc->sc_cm_cap, &sc->sc_acm_cap);

    usbd_claim_iface(sc->sc_udev, data_iface_idx);
    sc->sc_data_iface = uaa->ifaces[data_iface_idx];
    id = usbd_get_interface_descriptor(sc->sc_data_iface);

    printf("%s: data interface %d, has %sCM over data, has %sbreak\n",
           sc->sc_dev.dv_xname, id->bInterfaceNumber,
           sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ",
           sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no ");

    /*
     * Find the bulk endpoints.
     * Iterate over all endpoints in the data interface and take note.
     */
    uca.bulkin = uca.bulkout = -1;

    for (i = 0; i < id->bNumEndpoints; i++) {
        ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
        if (ed == NULL) {
            printf("%s: no endpoint descriptor for %d\n",
                   sc->sc_dev.dv_xname, i);
            goto bad;
        }
        if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
            uca.bulkin = ed->bEndpointAddress;
        } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                   (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
            uca.bulkout = ed->bEndpointAddress;
        }
    }

    if (uca.bulkin == -1) {
        printf("%s: Could not find data bulk in\n",
               sc->sc_dev.dv_xname);
        goto bad;
    }
    if (uca.bulkout == -1) {
        printf("%s: Could not find data bulk out\n",
               sc->sc_dev.dv_xname);
        goto bad;
    }

    if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_ASSUME_CM_OVER_DATA) {
        sc->sc_cm_over_data = 1;
    } else {
        if (sc->sc_cm_cap & USB_CDC_CM_OVER_DATA) {
            if (sc->sc_acm_cap & USB_CDC_ACM_HAS_FEATURE)
                err = umodem_set_comm_feature(sc,
                                              UCDC_ABSTRACT_STATE, UCDC_DATA_MULTIPLEXED);
            else
                err = 0;
            if (err) {
                printf("%s: could not set data multiplex mode\n",
                       sc->sc_dev.dv_xname);
                goto bad;
            }
            sc->sc_cm_over_data = 1;
        }
    }

    /*
     * The standard allows for notification messages (to indicate things
     * like a modem hangup) to come in via an interrupt endpoint
     * off of the control interface.  Iterate over the endpoints on
     * the control interface and see if there are any interrupt
     * endpoints; if there are, then register it.
     */

    sc->sc_ctl_notify = -1;
    sc->sc_notify_pipe = NULL;

    id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
    for (i = 0; i < id->bNumEndpoints; i++) {
        ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
        if (ed == NULL)
            continue;

        if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
            printf("%s: status change notification available\n",
                   sc->sc_dev.dv_xname);
            sc->sc_ctl_notify = ed->bEndpointAddress;
        }
    }

    sc->sc_dtr = -1;

    uca.portno = UCOM_UNK_PORTNO;
    /* bulkin, bulkout set above */
    uca.ibufsize = UMODEMIBUFSIZE;
    uca.obufsize = UMODEMOBUFSIZE;
    uca.ibufsizepad = UMODEMIBUFSIZE;
    uca.opkthdrlen = 0;
    uca.device = sc->sc_udev;
    uca.iface = sc->sc_data_iface;
    uca.methods = &umodem_methods;
    uca.arg = sc;
    uca.info = NULL;

    DPRINTF(("umodem_attach: sc=%p\n", sc));
    sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);

    return;

bad:
    usbd_deactivate(sc->sc_udev);
}