Esempio n. 1
0
int
utpms_match(struct device *parent, void *match, void *aux)
{
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	usb_device_descriptor_t *udd;
	int i;
	uint16_t vendor, product;

	/*
	 * We just check if the vendor and product IDs have the magic numbers
	 * we expect.
	 */
	if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
		vendor = UGETW(udd->idVendor);
		product = UGETW(udd->idProduct);
		for (i = 0; i < nitems(utpms_devices); i++) {
			if (vendor == utpms_devices[i].vendor &&
			    product == utpms_devices[i].product)
				return (UMATCH_IFACECLASS);
		}
	}

	return (UMATCH_NONE);
}
Esempio n. 2
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 ret;

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

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

	ret = UMATCH_NONE;
	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;

	return (ret);
}
Esempio n. 3
0
int
uhub_match(struct device *parent, void *match, void *aux)
{
	struct usb_attach_arg *uaa = aux;
	usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);

	/*
	 * The subclass for hubs seems to be 0 for some and 1 for others,
	 * so we just ignore the subclass.
	 */
	if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB)
		return (UMATCH_DEVCLASS_DEVSUBCLASS);
	return (UMATCH_NONE);
}
Esempio n. 4
0
static int
uhub_match(device_t self)
{
	struct usb_attach_arg *uaa = device_get_ivars(self);
	usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);

	DPRINTFN(5,("uhub_match, dd=%p\n", dd));
	/*
	 * The subclass for hubs seems to be 0 for some and 1 for others,
	 * so we just ignore the subclass.
	 */
	if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB)
		return (UMATCH_DEVCLASS_DEVSUBCLASS);
	return (UMATCH_NONE);
}
Esempio n. 5
0
Static void
umass_fixup_yedata(struct umass_softc *sc)
{
	usb_device_descriptor_t *dd;

	dd = usbd_get_device_descriptor(sc->sc_udev);

	/*
	 * Revisions < 1.28 do not handle the interrupt endpoint very well.
	 */
	if (UGETW(dd->bcdDevice) < 0x128)
		sc->sc_wire = UMASS_WPROTO_CBI;
	else
		sc->sc_wire = UMASS_WPROTO_CBI_I;
}
Esempio n. 6
0
static int
ubt_match(device_t self)
{
	struct usb_attach_arg *uaa = device_get_ivars(self);
	usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);

	DPRINTFN(50, "ubt_match\n");

	if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
		return UMATCH_NONE;

	if (dd->bDeviceClass == UDCLASS_WIRELESS
	    && dd->bDeviceSubClass == UDSUBCLASS_RF
	    && dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
		return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO;
	return UMATCH_NONE;
}
Esempio n. 7
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);
}
Esempio n. 8
0
Static void
umass_fixup_yedata(struct umass_softc *sc)
{
	usb_device_descriptor_t *dd;

	dd = usbd_get_device_descriptor(sc->sc_udev);

	/*
	 * Revisions < 1.28 do not handle the interrupt endpoint very well.
	 */
	if (UGETW(dd->bcdDevice) < 0x128)
		sc->sc_wire = UMASS_WPROTO_CBI;
	else
		sc->sc_wire = UMASS_WPROTO_CBI_I;

	/*
	 * Revisions < 1.28 do not have the TEST UNIT READY command
	 * Revisions == 1.28 have a broken TEST UNIT READY
	 */
	if (UGETW(dd->bcdDevice) <= 0x128)
		sc->sc_busquirks |= PQUIRK_NOTUR;
}
Esempio n. 9
0
Static void
umass_fixup_sony(struct umass_softc *sc)
{
	usb_interface_descriptor_t *id;
	usb_device_descriptor_t *dd;

	id = usbd_get_interface_descriptor(sc->sc_iface);
	if (id->bInterfaceSubClass == 0xff) {
		dd = usbd_get_device_descriptor(sc->sc_udev);
		/*
		 * Many Sony DSC cameras share the same product ID, so the
		 * revision number is used to distinguish between them.
		 */
		switch (UGETW(dd->bcdDevice)) {
		case 0x611: /* Sony DSC-T10, rev 6.11 */
		case 0x600: /* Sony DSC-W50, rev 6.00 */
		case 0x500: /* Sony DSC-P41, rev 5.00 */
			sc->sc_cmd = UMASS_CPROTO_UFI;
			break;
		default:
			sc->sc_cmd = UMASS_CPROTO_SCSI;
		}
	}
}
static int
ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
{
	union {
		struct usb_interface_descriptor *idesc;
		struct usb_alt_interface *ai;
		struct usb_device_descriptor *ddesc;
		struct usb_config_descriptor *cdesc;
		struct usb_device_stats *stat;
		struct usb_fs_init *pinit;
		struct usb_fs_uninit *puninit;
		uint32_t *ptime;
		void   *addr;
		int    *pint;
	}     u;
	struct usb_device_descriptor *dtemp;
	struct usb_config_descriptor *ctemp;
	struct usb_interface *iface;
	int error = 0;
	uint8_t n;

	u.addr = addr;

	DPRINTFN(6, "cmd=0x%08lx\n", cmd);

	switch (cmd) {
	case USB_DISCOVER:
		usb_needs_explore_all();
		break;

	case USB_SETDEBUG:
		if (!(fflags & FWRITE)) {
			error = EPERM;
			break;
		}
		usb_debug = *(int *)addr;
		break;

	case USB_GET_CONFIG:
		*(int *)addr = f->udev->curr_config_index;
		break;

	case USB_SET_CONFIG:
		if (!(fflags & FWRITE)) {
			error = EPERM;
			break;
		}
		error = ugen_set_config(f, *(int *)addr);
		break;

	case USB_GET_ALTINTERFACE:
		iface = usbd_get_iface(f->udev,
		    u.ai->uai_interface_index);
		if (iface && iface->idesc) {
			u.ai->uai_alt_index = iface->alt_index;
		} else {
			error = EINVAL;
		}
		break;

	case USB_SET_ALTINTERFACE:
		if (!(fflags & FWRITE)) {
			error = EPERM;
			break;
		}
		error = ugen_set_interface(f,
		    u.ai->uai_interface_index, u.ai->uai_alt_index);
		break;

	case USB_GET_DEVICE_DESC:
		dtemp = usbd_get_device_descriptor(f->udev);
		if (!dtemp) {
			error = EIO;
			break;
		}
		*u.ddesc = *dtemp;
		break;

	case USB_GET_CONFIG_DESC:
		ctemp = usbd_get_config_descriptor(f->udev);
		if (!ctemp) {
			error = EIO;
			break;
		}
		*u.cdesc = *ctemp;
		break;

	case USB_GET_FULL_DESC:
		error = ugen_get_cdesc(f, addr);
		break;

	case USB_GET_STRING_DESC:
		error = ugen_get_sdesc(f, addr);
		break;

	case USB_GET_IFACE_DRIVER:
		error = ugen_get_iface_driver(f, addr);
		break;

	case USB_REQUEST:
	case USB_DO_REQUEST:
		if (!(fflags & FWRITE)) {
			error = EPERM;
			break;
		}
		error = ugen_do_request(f, addr);
		break;

	case USB_DEVICEINFO:
	case USB_GET_DEVICEINFO:
		error = usb_gen_fill_deviceinfo(f, addr);
		break;

	case USB_DEVICESTATS:
		for (n = 0; n != 4; n++) {

			u.stat->uds_requests_fail[n] =
			    f->udev->bus->stats_err.uds_requests[n];

			u.stat->uds_requests_ok[n] =
			    f->udev->bus->stats_ok.uds_requests[n];
		}
		break;

	case USB_DEVICEENUMERATE:
		error = ugen_re_enumerate(f);
		break;

	case USB_GET_PLUGTIME:
		*u.ptime = f->udev->plugtime;
		break;

	case USB_CLAIM_INTERFACE:
	case USB_RELEASE_INTERFACE:
		/* TODO */
		break;

	case USB_IFACE_DRIVER_ACTIVE:
		/* TODO */
		*u.pint = 0;
		break;

	case USB_IFACE_DRIVER_DETACH:
		/* TODO */
		error = priv_check(curthread, PRIV_DRIVER);
		if (error) {
			break;
		}
		error = EINVAL;
		break;

	case USB_SET_POWER_MODE:
		error = ugen_set_power_mode(f, *u.pint);
		break;

	case USB_GET_POWER_MODE:
		*u.pint = ugen_get_power_mode(f);
		break;

	case USB_SET_PORT_ENABLE:
		error = ugen_do_port_feature(f,
		    *u.pint, 1, UHF_PORT_ENABLE);
		break;

	case USB_SET_PORT_DISABLE:
		error = ugen_do_port_feature(f,
		    *u.pint, 0, UHF_PORT_ENABLE);
		break;

	case USB_FS_INIT:
		/* verify input parameters */
		if (u.pinit->pEndpoints == NULL) {
			error = EINVAL;
			break;
		}
		if (u.pinit->ep_index_max > 127) {
			error = EINVAL;
			break;
		}
		if (u.pinit->ep_index_max == 0) {
			error = EINVAL;
			break;
		}
		if (f->fs_xfer != NULL) {
			error = EBUSY;
			break;
		}
		if (f->dev_ep_index != 0) {
			error = EINVAL;
			break;
		}
		if (ugen_fifo_in_use(f, fflags)) {
			error = EBUSY;
			break;
		}
		error = usb_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max);
		if (error) {
			break;
		}
		f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) *
		    u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO);
		if (f->fs_xfer == NULL) {
			usb_fifo_free_buffer(f);
			error = ENOMEM;
			break;
		}
		f->fs_ep_max = u.pinit->ep_index_max;
		f->fs_ep_ptr = u.pinit->pEndpoints;
		break;

	case USB_FS_UNINIT:
		if (u.puninit->dummy != 0) {
			error = EINVAL;
			break;
		}
		error = ugen_fs_uninit(f);
		break;

	default:
		mtx_lock(f->priv_mtx);
		error = ugen_iface_ioctl(f, cmd, addr, fflags);
		mtx_unlock(f->priv_mtx);
		break;
	}
	DPRINTFN(6, "error=%d\n", error);
	return (error);
}
Esempio n. 11
0
void
uticom_attach_hook(void *arg)
{
	struct uticom_softc		*sc = arg;
	usb_config_descriptor_t		*cdesc;
	usb_interface_descriptor_t	*id;
	usb_endpoint_descriptor_t	*ed;
	usbd_status			 err;
	int				 status, i;
	usb_device_descriptor_t		*dd;
	struct ucom_attach_args		 uca;

	/* Initialize endpoints. */
	uca.bulkin = uca.bulkout = -1;
	sc->sc_intr_number = -1;
	sc->sc_intr_pipe = NULL;

	dd = usbd_get_device_descriptor(sc->sc_udev);
	DPRINTF(("%s: uticom_attach: num of configurations %d\n",
	    sc->sc_dev.dv_xname, dd->bNumConfigurations));

	/* The device without firmware has single configuration with single
	 * bulk out interface. */
	if (dd->bNumConfigurations > 1)
		goto fwload_done;

	/* Loading firmware. */
	DPRINTF(("%s: uticom_attach: starting loading firmware\n",
	    sc->sc_dev.dv_xname));

	err = usbd_set_config_index(sc->sc_udev, UTICOM_CONFIG_INDEX, 1);
	if (err) {
		printf("%s: failed to set configuration: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Get the config descriptor. */
	cdesc = usbd_get_config_descriptor(sc->sc_udev);

	if (cdesc == NULL) {
		printf("%s: failed to get configuration descriptor\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX,
	    &sc->sc_iface);
	if (err) {
		printf("%s: failed to get interface: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Find the bulk out interface used to upload firmware. */
	id = usbd_get_interface_descriptor(sc->sc_iface);
	sc->sc_iface_number = id->bInterfaceNumber;

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

		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			uca.bulkout = ed->bEndpointAddress;
			DPRINTF(("%s: uticom_attach: data bulk out num: %d\n",
			    sc->sc_dev.dv_xname, ed->bEndpointAddress));
		}

		if (uca.bulkout == -1) {
			printf("%s: could not find data bulk out\n",
			    sc->sc_dev.dv_xname);
			usbd_deactivate(sc->sc_udev);
			return;
		}
	}

	status = uticom_download_fw(sc, uca.bulkout, sc->sc_udev);

	if (status) {
		printf("%s: firmware download failed\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	} else {
		DPRINTF(("%s: firmware download succeeded\n",
		    sc->sc_dev.dv_xname));
	}

	status = usbd_reload_device_desc(sc->sc_udev);
	if (status) {
		printf("%s: error reloading device descriptor\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

fwload_done:
	dd = usbd_get_device_descriptor(sc->sc_udev);
	DPRINTF(("%s: uticom_attach: num of configurations %d\n",
	    sc->sc_dev.dv_xname, dd->bNumConfigurations));

	err = usbd_set_config_index(sc->sc_udev, UTICOM_ACTIVE_INDEX, 1);
	if (err) {
		printf("%s: failed to set configuration: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Get the config descriptor. */
	cdesc = usbd_get_config_descriptor(sc->sc_udev);
	if (cdesc == NULL) {
		printf("%s: failed to get configuration descriptor\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Get the interface (XXX: multiport chips are not supported yet). */
	err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX,
	    &sc->sc_iface);
	if (err) {
		printf("%s: failed to get interface: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Find the interrupt endpoints. */
	id = usbd_get_interface_descriptor(sc->sc_iface);
	sc->sc_iface_number = id->bInterfaceNumber;

	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
		if (ed == NULL) {
			printf("%s: no endpoint descriptor 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);

		}
	}

	if (sc->sc_intr_number == -1) {
		printf("%s: could not find interrupt in\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	/* Keep interface for interrupt. */
	sc->sc_intr_iface = sc->sc_iface;

	/* Find the bulk{in,out} endpoints. */
	id = usbd_get_interface_descriptor(sc->sc_iface);
	sc->sc_iface_number = id->bInterfaceNumber;

	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
		if (ed == NULL) {
			printf("%s: no endpoint descriptor 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_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) {
		printf("%s: could not find data bulk in\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	if (uca.bulkout == -1) {
		printf("%s: could not find data bulk out\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

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

	uca.portno = UCOM_UNK_PORTNO;
	uca.ibufsize = UTICOM_IBUFSZ;
	uca.obufsize = UTICOM_OBUFSZ;
	uca.ibufsizepad = UTICOM_IBUFSZ;
	uca.device = sc->sc_udev;
	uca.iface = sc->sc_iface;
	uca.opkthdrlen = 0;
	uca.methods = &uticom_methods;
	uca.arg = sc;
	uca.info = NULL;

	err = uticom_reset(sc);
	if (err) {
		printf("%s: reset failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		usbd_deactivate(sc->sc_udev);
		return;
	}

	DPRINTF(("%s: uticom_attach: in = 0x%x, out = 0x%x, intr = 0x%x\n",
	    sc->sc_dev.dv_xname, uca.bulkin,
	    uca.bulkout, sc->sc_intr_number));

	sc->sc_subdev = config_found_sm((struct device *)sc, &uca, ucomprint, ucomsubmatch);
}
Esempio n. 12
0
void
utpms_attach(struct device *parent, struct device *self, void *aux)
{
	struct utpms_softc *sc = (struct utpms_softc *)self;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
	struct wsmousedev_attach_args a;
	struct utpms_dev *pd;
	usb_device_descriptor_t *udd;
	int i;
	uint16_t vendor, product;

	sc->sc_datalen = UTPMS_DATA_LEN;
	sc->sc_hdev.sc_udev = uha->uaa->device;

	/* Fill in device-specific parameters. */
	if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
		product = UGETW(udd->idProduct);
		vendor = UGETW(udd->idVendor);
		for (i = 0; i < nitems(utpms_devices); i++) {
			pd = &utpms_devices[i];
			if (product == pd->product && vendor == pd->vendor) {
				switch (pd->type) {
				case FOUNTAIN:
					printf(": Fountain");
					break;
				case GEYSER1:
					printf(": Geyser");
					break;
				case GEYSER2:
					sc->sc_type = GEYSER2;
					sc->sc_datalen = 64;
					sc->sc_y_sensors = 9;
					printf(": Geyser 2");
					break;
				}
				printf(" Trackpad\n");
				sc->sc_noise = pd->noise;
				sc->sc_threshold = pd->threshold;
				sc->sc_x_factor = pd->x_factor;
				sc->sc_x_sensors = pd->x_sensors;
				sc->sc_y_factor = pd->y_factor;
				sc->sc_y_sensors = pd->y_sensors;
				break;
			}
		}
	}
	if (sc->sc_x_sensors <= 0 || sc->sc_x_sensors > UTPMS_X_SENSORS ||
	    sc->sc_y_sensors <= 0 || sc->sc_y_sensors > UTPMS_Y_SENSORS) {
		printf(": unexpected sensors configuration (%d:%d)\n",
		    sc->sc_x_sensors, sc->sc_y_sensors);
		return;
	}

	sc->sc_hdev.sc_intr = utpms_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	sc->sc_status = 0;

	a.accessops = &utpms_accessops;
	a.accesscookie = sc;
	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
Esempio n. 13
0
void 
uftdi_attach(device_t parent, device_t self, void *aux)
{
	struct uftdi_softc *sc = device_private(self);
	struct usb_attach_arg *uaa = aux;
	usbd_device_handle dev = uaa->device;
	usbd_interface_handle iface;
	usb_device_descriptor_t *ddesc;
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	char *devinfop;
	const char *devname = device_xname(self);
	int i,idx;
	usbd_status err;
	struct ucom_attach_args uca;

	DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc));

	aprint_naive("\n");
	aprint_normal("\n");

	devinfop = usbd_devinfo_alloc(dev, 0);
	aprint_normal_dev(self, "%s\n", devinfop);
	usbd_devinfo_free(devinfop);

	/* Move the device into the configured state. */
	err = usbd_set_config_index(dev, UFTDI_CONFIG_INDEX, 1);
	if (err) {
		aprint_error("\n%s: failed to set configuration, err=%s\n",
		       devname, usbd_errstr(err));
		goto bad;
	}

	sc->sc_dev = self;
	sc->sc_udev = dev;
	sc->sc_numports = 1;
	sc->sc_type = UFTDI_TYPE_8U232AM; /* most devices are post-8U232AM */
	sc->sc_hdrlen = 0;
	if (uaa->vendor == USB_VENDOR_FTDI
	    && uaa->product == USB_PRODUCT_FTDI_SERIAL_8U100AX) {
		sc->sc_type = UFTDI_TYPE_SIO;
		sc->sc_hdrlen = 1;
	}

	ddesc = usbd_get_device_descriptor(dev);
	sc->sc_chiptype = UGETW(ddesc->bcdDevice);
	switch (sc->sc_chiptype) {
	case 0x500: /* 2232D */
	case 0x700: /* 2232H */
		sc->sc_numports = 2;
		break;
	case 0x800: /* 4232H */
		sc->sc_numports = 4;
		break;
	case 0x200: /* 232/245AM */
	case 0x400: /* 232/245BL */
	case 0x600: /* 232/245R */
	default:
		break;
	}

	for (idx = UFTDI_IFACE_INDEX; idx < sc->sc_numports; idx++) {
		err = usbd_device2interface_handle(dev, idx, &iface);
		if (err) {
			aprint_error(
			    "\n%s: failed to get interface idx=%d, err=%s\n",
			    devname, idx, usbd_errstr(err));
			goto bad;
		}

		id = usbd_get_interface_descriptor(iface);

		sc->sc_iface[idx] = iface;

		uca.bulkin = uca.bulkout = -1;
		uca.ibufsize = uca.obufsize = 0;
		for (i = 0; i < id->bNumEndpoints; i++) {
			int addr, dir, attr;
			ed = usbd_interface2endpoint_descriptor(iface, i);
			if (ed == NULL) {
				aprint_error_dev(self,
				    "could not read endpoint descriptor: %s\n",
				    usbd_errstr(err));
				goto bad;
			}

			addr = ed->bEndpointAddress;
			dir = UE_GET_DIR(ed->bEndpointAddress);
			attr = ed->bmAttributes & UE_XFERTYPE;
			if (dir == UE_DIR_IN && attr == UE_BULK) {
				uca.bulkin = addr;
				uca.ibufsize = UGETW(ed->wMaxPacketSize);
				if (uca.ibufsize >= UFTDI_MAX_IBUFSIZE)
					uca.ibufsize = UFTDI_MAX_IBUFSIZE;
			} else if (dir == UE_DIR_OUT && attr == UE_BULK) {
				uca.bulkout = addr;
				uca.obufsize = UGETW(ed->wMaxPacketSize)
				    - sc->sc_hdrlen;
				if (uca.obufsize >= UFTDI_MAX_OBUFSIZE)
					uca.obufsize = UFTDI_MAX_OBUFSIZE;
				/* Limit length if we have a 6-bit header.  */
				if ((sc->sc_hdrlen > 0) &&
				    (uca.obufsize > UFTDIOBUFSIZE))
					uca.obufsize = UFTDIOBUFSIZE;
			} else {
				aprint_error_dev(self,
				    "unexpected endpoint\n");
				goto bad;
			}
		}
		if (uca.bulkin == -1) {
			aprint_error_dev(self,
			    "Could not find data bulk in\n");
			goto bad;
		}
		if (uca.bulkout == -1) {
			aprint_error_dev(self,
			    "Could not find data bulk out\n");
			goto bad;
		}

		uca.portno = FTDI_PIT_SIOA + idx;
		/* bulkin, bulkout set above */
		if (uca.ibufsize == 0)
			uca.ibufsize = UFTDIIBUFSIZE;
		uca.ibufsizepad = uca.ibufsize;
		if (uca.obufsize == 0)
			uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
		uca.opkthdrlen = sc->sc_hdrlen;
		uca.device = dev;
		uca.iface = iface;
		uca.methods = &uftdi_methods;
		uca.arg = sc;
		uca.info = NULL;

		DPRINTF(("uftdi: in=0x%x out=0x%x isize=0x%x osize=0x%x\n",
			uca.bulkin, uca.bulkout,
			uca.ibufsize, uca.obufsize));
		sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL,
		    &uca, ucomprint, ucomsubmatch);
	}

	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
			   sc->sc_dev);

	return;

bad:
	DPRINTF(("uftdi_attach: ATTACH ERROR\n"));
	sc->sc_dying = 1;
	return;
}
Esempio n. 14
0
int
ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
	      caddr_t addr, int flag, struct proc *p)
{
	struct ugen_endpoint *sce;
	int err;
	struct usbd_interface *iface;
	struct usb_config_desc *cd;
	usb_config_descriptor_t *cdesc;
	struct usb_interface_desc *id;
	usb_interface_descriptor_t *idesc;
	struct usb_endpoint_desc *ed;
	usb_endpoint_descriptor_t *edesc;
	struct usb_alt_interface *ai;
	struct usb_string_desc *si;
	u_int8_t conf, alt;

	DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
	if (usbd_is_dying(sc->sc_udev))
		return (EIO);

	switch (cmd) {
	case FIONBIO:
		/* All handled in the upper FS layer. */
		return (0);
	case USB_SET_SHORT_XFER:
		if (endpt == USB_CONTROL_ENDPOINT)
			return (EINVAL);
		/* This flag only affects read */
		sce = &sc->sc_endpoints[endpt][IN];
		if (sce == NULL || sce->pipeh == NULL)
			return (EINVAL);
		if (*(int *)addr)
			sce->state |= UGEN_SHORT_OK;
		else
			sce->state &= ~UGEN_SHORT_OK;
		return (0);
	case USB_SET_TIMEOUT:
		sce = &sc->sc_endpoints[endpt][IN];
		if (sce == NULL)
			return (EINVAL);
		sce->timeout = *(int *)addr;
		sce = &sc->sc_endpoints[endpt][OUT];
		if (sce == NULL)
			return (EINVAL);
		sce->timeout = *(int *)addr;
		return (0);
	default:
		break;
	}

	if (endpt != USB_CONTROL_ENDPOINT)
		return (EINVAL);

	switch (cmd) {
#ifdef UGEN_DEBUG
	case USB_SETDEBUG:
		ugendebug = *(int *)addr;
		break;
#endif
	case USB_GET_CONFIG:
		err = usbd_get_config(sc->sc_udev, &conf);
		if (err)
			return (EIO);
		*(int *)addr = conf;
		break;
	case USB_SET_CONFIG:
		if (!(flag & FWRITE))
			return (EPERM);
		err = ugen_set_config(sc, *(int *)addr);
		switch (err) {
		case USBD_NORMAL_COMPLETION:
			break;
		case USBD_IN_USE:
			return (EBUSY);
		default:
			return (EIO);
		}
		break;
	case USB_GET_ALTINTERFACE:
		ai = (struct usb_alt_interface *)addr;
		err = usbd_device2interface_handle(sc->sc_udev,
			  ai->uai_interface_index, &iface);
		if (err)
			return (EINVAL);
		idesc = usbd_get_interface_descriptor(iface);
		if (idesc == NULL)
			return (EIO);
		ai->uai_alt_no = idesc->bAlternateSetting;
		break;
	case USB_SET_ALTINTERFACE:
		if (!(flag & FWRITE))
			return (EPERM);
		ai = (struct usb_alt_interface *)addr;
		err = usbd_device2interface_handle(sc->sc_udev,
			  ai->uai_interface_index, &iface);
		if (err)
			return (EINVAL);
		err = ugen_set_interface(sc, ai->uai_interface_index,
		    ai->uai_alt_no);
		if (err)
			return (EINVAL);
		break;
	case USB_GET_NO_ALT:
		ai = (struct usb_alt_interface *)addr;
		cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index, 0);
		if (cdesc == NULL)
			return (EINVAL);
		idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
		if (idesc == NULL) {
			free(cdesc, M_TEMP, 0);
			return (EINVAL);
		}
		ai->uai_alt_no = usbd_get_no_alts(cdesc,
		    idesc->bInterfaceNumber);
		free(cdesc, M_TEMP, 0);
		break;
	case USB_GET_DEVICE_DESC:
		*(usb_device_descriptor_t *)addr =
			*usbd_get_device_descriptor(sc->sc_udev);
		break;
	case USB_GET_CONFIG_DESC:
		cd = (struct usb_config_desc *)addr;
		cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index, 0);
		if (cdesc == NULL)
			return (EINVAL);
		cd->ucd_desc = *cdesc;
		free(cdesc, M_TEMP, 0);
		break;
	case USB_GET_INTERFACE_DESC:
		id = (struct usb_interface_desc *)addr;
		cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index, 0);
		if (cdesc == NULL)
			return (EINVAL);
		if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
		    id->uid_alt_index == USB_CURRENT_ALT_INDEX)
			alt = ugen_get_alt_index(sc, id->uid_interface_index);
		else
			alt = id->uid_alt_index;
		idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
		if (idesc == NULL) {
			free(cdesc, M_TEMP, 0);
			return (EINVAL);
		}
		id->uid_desc = *idesc;
		free(cdesc, M_TEMP, 0);
		break;
	case USB_GET_ENDPOINT_DESC:
		ed = (struct usb_endpoint_desc *)addr;
		cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index, 0);
		if (cdesc == NULL)
			return (EINVAL);
		if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
		    ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
			alt = ugen_get_alt_index(sc, ed->ued_interface_index);
		else
			alt = ed->ued_alt_index;
		edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
					alt, ed->ued_endpoint_index);
		if (edesc == NULL) {
			free(cdesc, M_TEMP, 0);
			return (EINVAL);
		}
		ed->ued_desc = *edesc;
		free(cdesc, M_TEMP, 0);
		break;
	case USB_GET_FULL_DESC:
	{
		int len;
		struct iovec iov;
		struct uio uio;
		struct usb_full_desc *fd = (struct usb_full_desc *)addr;
		int error;

		cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index, &len);
		if (cdesc == NULL)
			return (EINVAL);
		if (len > fd->ufd_size)
			len = fd->ufd_size;
		iov.iov_base = (caddr_t)fd->ufd_data;
		iov.iov_len = len;
		uio.uio_iov = &iov;
		uio.uio_iovcnt = 1;
		uio.uio_resid = len;
		uio.uio_offset = 0;
		uio.uio_segflg = UIO_USERSPACE;
		uio.uio_rw = UIO_READ;
		uio.uio_procp = p;
		error = uiomove((void *)cdesc, len, &uio);
		free(cdesc, M_TEMP, 0);
		return (error);
	}
	case USB_GET_STRING_DESC:
	{
		int len;
		si = (struct usb_string_desc *)addr;
		err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
			si->usd_language_id, &si->usd_desc, &len);
		if (err)
			return (EINVAL);
		break;
	}
	case USB_DO_REQUEST:
	{
		struct usb_ctl_request *ur = (void *)addr;
		int len = UGETW(ur->ucr_request.wLength);
		struct iovec iov;
		struct uio uio;
		void *ptr = 0;
		int error = 0;

		if (!(flag & FWRITE))
			return (EPERM);
		/* Avoid requests that would damage the bus integrity. */
		if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
		     ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
		    (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
		     ur->ucr_request.bRequest == UR_SET_CONFIG) ||
		    (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
		     ur->ucr_request.bRequest == UR_SET_INTERFACE))
			return (EINVAL);

		if (len < 0 || len > 32767)
			return (EINVAL);
		if (len != 0) {
			iov.iov_base = (caddr_t)ur->ucr_data;
			iov.iov_len = len;
			uio.uio_iov = &iov;
			uio.uio_iovcnt = 1;
			uio.uio_resid = len;
			uio.uio_offset = 0;
			uio.uio_segflg = UIO_USERSPACE;
			uio.uio_rw =
				ur->ucr_request.bmRequestType & UT_READ ?
				UIO_READ : UIO_WRITE;
			uio.uio_procp = p;
			ptr = malloc(len, M_TEMP, M_WAITOK);
			if (uio.uio_rw == UIO_WRITE) {
				error = uiomove(ptr, len, &uio);
				if (error)
					goto ret;
			}
		}
		sce = &sc->sc_endpoints[endpt][IN];
		err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
			  ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
		if (err) {
			error = EIO;
			goto ret;
		}
		/* Only if USBD_SHORT_XFER_OK is set. */
		if (len > ur->ucr_actlen)
			len = ur->ucr_actlen;
		if (len != 0) {
			if (uio.uio_rw == UIO_READ) {
				error = uiomove(ptr, len, &uio);
				if (error)
					goto ret;
			}
		}
	ret:
		if (ptr)
			free(ptr, M_TEMP, 0);
		return (error);
	}
	case USB_GET_DEVICEINFO:
		usbd_fill_deviceinfo(sc->sc_udev,
				     (struct usb_device_info *)addr, 1);
		break;
	default:
		return (EINVAL);
	}
	return (0);
}
Esempio n. 15
0
void
ubcmtp_attach(struct device *parent, struct device *self, void *aux)
{
	struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct usbd_device *dev = uaa->device;
	struct wsmousedev_attach_args a;
	usb_device_descriptor_t *udd;
	int i;

	sc->sc_udev = uaa->device;
	sc->sc_status = 0;

	if ((udd = usbd_get_device_descriptor(dev)) == NULL) {
		printf("ubcmtp: failed getting device descriptor\n");
		return;
	}

	for (i = 0; i < nitems(ubcmtp_devices); i++) {
		if (uaa->vendor == ubcmtp_devices[i].vendor && (
		    uaa->product == ubcmtp_devices[i].ansi ||
		    uaa->product == ubcmtp_devices[i].iso ||
		    uaa->product == ubcmtp_devices[i].jis)) {
			sc->dev_type = &ubcmtp_devices[i];
			DPRINTF("%s: attached to 0x%x/0x%x type %d\n",
			    sc->sc_dev.dv_xname, uaa->vendor, uaa->product,
			    sc->dev_type->type);
			break;
		}
	}

	if (sc->dev_type == NULL) {
		/* how did we match then? */
		printf("%s: failed looking up device in table\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	switch (sc->dev_type->type) {
	case UBCMTP_TYPE1:
		sc->tp_maxlen = UBCMTP_TYPE1_TPLEN;
		sc->tp_offset = UBCMTP_TYPE1_TPOFF;
		sc->tp_ifacenum = UBCMTP_TYPE1_TPIFACE;

		/* button offsets */
		sc->bt_maxlen = sizeof(struct ubcmtp_button);
		sc->bt_ifacenum = UBCMTP_TYPE1_BTIFACE;
		break;

	case UBCMTP_TYPE2:
		sc->tp_maxlen = UBCMTP_TYPE2_TPLEN;
		sc->tp_offset = UBCMTP_TYPE2_TPOFF;
		sc->tp_ifacenum = UBCMTP_TYPE2_TPIFACE;
		break;

	case UBCMTP_TYPE3:
		sc->tp_maxlen = UBCMTP_TYPE3_TPLEN;
		sc->tp_offset = UBCMTP_TYPE3_TPOFF;
		sc->tp_ifacenum = UBCMTP_TYPE3_TPIFACE;
		break;
	}

	a.accessops = &ubcmtp_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
Esempio n. 16
0
int
kue_load_fw(struct kue_softc *sc)
{
	usb_device_descriptor_t *dd;
	usbd_status		err;
	struct kue_firmware	*fw;
	u_char			*buf;
	size_t			buflen;

	DPRINTFN(1,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));

	/*
	 * First, check if we even need to load the firmware.
	 * If the device was still attached when the system was
	 * rebooted, it may already have firmware loaded in it.
	 * If this is the case, we don't need to do it again.
	 * And in fact, if we try to load it again, we'll hang,
	 * so we have to avoid this condition if we don't want
	 * to look stupid.
	 *
	 * We can test this quickly by checking the bcdRevision
	 * code. The NIC will return a different revision code if
	 * it's probed while the firmware is still loaded and
	 * running.
	 */
	if ((dd = usbd_get_device_descriptor(sc->kue_udev)) == NULL)
		return (EIO);
	if (UGETW(dd->bcdDevice) >= KUE_WARM_REV) {
		printf("%s: warm boot, no firmware download\n",
		       sc->kue_dev.dv_xname);
		return (0);
	}

	err = loadfirmware("kue", &buf, &buflen);
	if (err) {
		printf("%s: failed loadfirmware of file %s: errno %d\n",
		    sc->kue_dev.dv_xname, "kue", err);
		return (err);
	}
	fw = (struct kue_firmware *)buf;

	printf("%s: cold boot, downloading firmware\n",
	       sc->kue_dev.dv_xname);

	/* Load code segment */
	DPRINTFN(1,("%s: kue_load_fw: download code_seg\n",
		    sc->kue_dev.dv_xname));
	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
	    0, (void *)&fw->data[0], ntohl(fw->codeseglen));
	if (err) {
		printf("%s: failed to load code segment: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		free(buf, M_DEVBUF, 0);
		return (EIO);
	}

	/* Load fixup segment */
	DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n",
		    sc->kue_dev.dv_xname));
	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
	    0, (void *)&fw->data[ntohl(fw->codeseglen)], ntohl(fw->fixseglen));
	if (err) {
		printf("%s: failed to load fixup segment: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		free(buf, M_DEVBUF, 0);
		return (EIO);
	}

	/* Send trigger command. */
	DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n",
		    sc->kue_dev.dv_xname));
	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
	    0, (void *)&fw->data[ntohl(fw->codeseglen) + ntohl(fw->fixseglen)],
	    ntohl(fw->trigseglen));
	if (err) {
		printf("%s: failed to load trigger segment: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		free(buf, M_DEVBUF, 0);
		return (EIO);
	}
	free(buf, M_DEVBUF, 0);

	usbd_delay_ms(sc->kue_udev, 10);

	/*
	 * Reload device descriptor.
	 * Why? The chip without the firmware loaded returns
	 * one revision code. The chip with the firmware
	 * loaded and running returns a *different* revision
	 * code. This confuses the quirk mechanism, which is
	 * dependent on the revision data.
	 */
	(void)usbd_reload_device_desc(sc->kue_udev);

	DPRINTFN(1,("%s: %s: done\n", sc->kue_dev.dv_xname, __func__));

	/* Reset the adapter. */
	kue_reset(sc);

	return (0);
}