Beispiel #1
0
int
umsm_match(struct device *parent, void *match, void *aux)
{
	struct usb_attach_arg *uaa = aux;
	usb_interface_descriptor_t *id;
	uint16_t flag;

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

	/*
	 * Some devices (eg Huawei E220) have multiple interfaces and some
	 * of them are of class umass. Don't claim ownership in such case.
	 */
	if (umsm_lookup(uaa->vendor, uaa->product) != NULL) {
		id = usbd_get_interface_descriptor(uaa->iface);
		flag = umsm_lookup(uaa->vendor, uaa->product)->umsm_flag;

		if (id == NULL || id->bInterfaceClass == UICLASS_MASS) {
			/*
			 * Some high-speed modems require special care.
			 */
			if (flag & DEV_HUAWEI) {
				if (uaa->ifaceno != 2)
					return UMATCH_VENDOR_IFACESUBCLASS;
				else
					return UMATCH_NONE;
			} else if (flag & DEV_UMASS) {
				return UMATCH_VENDOR_IFACESUBCLASS;
			} else if (flag & DEV_TRUINSTALL) {
				return UMATCH_VENDOR_IFACESUBCLASS;
			} else
				return UMATCH_NONE;
		/*
		 * Some devices have interfaces which fail to attach but in
		 * addition seem to make the remaining interfaces unusable. Only
		 * attach whitelisted interfaces in this case.
		 */
		} else if ((uaa->vendor == USB_VENDOR_MEDIATEK &&
			    uaa->product == USB_PRODUCT_MEDIATEK_DC_4COM) &&
			   !(id->bInterfaceClass == UICLASS_VENDOR &&
			    ((id->bInterfaceSubClass == 0x02 &&
			      id->bInterfaceProtocol == 0x01) ||
			     (id->bInterfaceSubClass == 0x00 &&
			      id->bInterfaceProtocol == 0x00)))) {
			return UMATCH_NONE;
		} else
			return UMATCH_VENDOR_IFACESUBCLASS;
	}

	return UMATCH_NONE;
}
Beispiel #2
0
int
umsm_match(struct device *parent, void *match, void *aux)
{
	struct usb_attach_arg *uaa = aux;
	usb_interface_descriptor_t *id;
	uint16_t flag;

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

	/*
	 * Some devices (eg Huawei E220) have multiple interfaces and some
	 * of them are of class umass. Don't claim ownership in such case.
	 */
	if (umsm_lookup(uaa->vendor, uaa->product) != NULL) {
		id = usbd_get_interface_descriptor(uaa->iface);
		flag = umsm_lookup(uaa->vendor, uaa->product)->umsm_flag;

		if (id == NULL || id->bInterfaceClass == UICLASS_MASS) {
			/*
			 * Some high-speed modems require special care.
			 */
			if (flag & DEV_HUAWEI) {
				if (uaa->ifaceno != 2)
					return UMATCH_VENDOR_IFACESUBCLASS;
				else
					return UMATCH_NONE;
			} else if (flag & DEV_UMASS) {
				return UMATCH_VENDOR_IFACESUBCLASS;
			} else if (flag & DEV_TRUINSTALL) {
				return UMATCH_VENDOR_IFACESUBCLASS;
			} else
				return UMATCH_NONE;
		} else
			return UMATCH_VENDOR_IFACESUBCLASS;
	}

	return UMATCH_NONE;
}
Beispiel #3
0
void
umsm_attach(struct device *parent, struct device *self, void *aux)
{
	struct umsm_softc *sc = (struct umsm_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct ucom_attach_args uca;
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	int i;

	bzero(&uca, sizeof(uca));
	sc->sc_udev = uaa->device;
	sc->sc_iface = uaa->iface;
	sc->sc_flag  = umsm_lookup(uaa->vendor, uaa->product)->umsm_flag;

	id = usbd_get_interface_descriptor(sc->sc_iface);

	/*
	 * Some 3G modems have multiple interfaces and some of them
	 * are umass class. Don't claim ownership in such case.
	 */
	if (id == NULL || id->bInterfaceClass == UICLASS_MASS) {
		/*
		 * Some 3G modems require a special request to
		 * enable their modem function.
		 */
		if ((sc->sc_flag & DEV_HUAWEI) && uaa->ifaceno == 0) {
                        umsm_huawei_changemode(uaa->device);
			printf("%s: umass only mode. need to reattach\n",
				sc->sc_dev.dv_xname);
		} else if ((sc->sc_flag & DEV_TRUINSTALL) &&
			    uaa->ifaceno == 0) {
			umsm_truinstall_changemode(uaa->device);
			printf("%s: truinstall mode. need to reattach\n",
				sc->sc_dev.dv_xname);
		} else if ((sc->sc_flag & DEV_UMASS) && uaa->ifaceno == 0) {
			umsm_umass_changemode(sc);
		}

		/*
		 * The device will reset its own bus from the device side
		 * when its mode was changed, so just return.
		 */
		return;
	}

	sc->sc_iface_no = id->bInterfaceNumber;
	uca.bulkin = uca.bulkout = -1;
	sc->sc_intr_number = sc->sc_isize = -1;
	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
		if (ed == NULL) {
			printf("%s: no endpoint descriptor found for %d\n",
			    sc->sc_dev.dv_xname, i);
			usbd_deactivate(sc->sc_udev);
			return;
		}

		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
			sc->sc_intr_number = ed->bEndpointAddress;
			sc->sc_isize = UGETW(ed->wMaxPacketSize);
			DPRINTF(("%s: find interrupt endpoint for %s\n",
				__func__, sc->sc_dev.dv_xname));
		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
			uca.bulkin = ed->bEndpointAddress;
		else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
			uca.bulkout = ed->bEndpointAddress;
	}
	if (uca.bulkin == -1 || uca.bulkout == -1) {
		printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	sc->sc_dtr = sc->sc_rts = -1;

	/* We need to force size as some devices lie */
	uca.ibufsize = UMSMBUFSZ;
	uca.obufsize = UMSMBUFSZ;
	uca.ibufsizepad = UMSMBUFSZ;
	uca.opkthdrlen = 0;
	uca.device = sc->sc_udev;
	uca.iface = sc->sc_iface;
	uca.methods = &umsm_methods;
	uca.arg = sc;
	uca.info = NULL;
	uca.portno = UCOM_UNK_PORTNO;

	sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
}