Help getting Option N.V. Fusion UMTS Quad-GPRS run

guru at Sisis.de guru at Sisis.de
Thu Nov 3 00:00:43 PST 2005


El día Wednesday, November 02, 2005 a las 08:08:37PM +0100, Rehsack Jens (ext) escribió:

> Hi all,
> 
> with the workaround from Warner I get the card below activated, but it
> seems to
> me, that the devices after the USB Hub on the card are adressed with the
> wrong
> bus id, too.
> 
> Does anyone has an idea, how I can set the appropriate bus id's, so that
> the card
> will work properly?

Hello Jens,

maybe the attached files help you out somehow; I got mine UMTS
card to work;

attached you will find the following documents:
 
- umts.txt describing all the details I know;
- a modified source /usr/src/sys/dev/usb/uftdi.c
  for the uftdi.ko kernel module
- a diff for /usr/src/sys/dev/usb/usbdevs
- a diff for /usr/src/sys/dev/usb/ucom.c
 
        matthias
-- 
Matthias Apitz / Sisis Informationssysteme GmbH
Gruenwalder Weg 28g / D-82041 Oberhaching
Fon: ++49 89 / 61308-351, Fax: -399, Mobile ++49 170 4527211
http://www.sisis.de/~guru/
-------------- next part --------------
100,101d99
< /* #define USB_DEBUG 1 */
< 
103c101
< static int	ucomdebug = 10;
---
> static int	ucomdebug = 0;
-------------- next part --------------
/*	$NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $	*/

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Lennart Augustsson (lennart at augustsson.net).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by the NetBSD
 *        Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/usb/uftdi.c,v 1.18.2.1 2005/01/30 01:00:10 imp Exp $");

/*
 * FTDI FT8U100AX serial adapter driver
 */

/*
 * UMTS:
 *
 * This driver was modified to support a PCMCIA card:
 *     Manufacturer: Option N.V.
 *     Model: GlobeTrotter Fusion Quad Lite
 *     Revision: 1.5.5  (Date: May 17 2005, Time: 14:55:44)
 *
 * The changes mostly consist in skipping parts of the driver, for example
 * baudrate settings and so on, not supported by the card. The ideas came
 * from Andrew Gordon <arg at arg.me.uk>
 *
 * domingo, 2 de octubre de 2005, 09:34:24 CEST, Matthias Apitz <guru at Sisis.de>
 */

#include <sys/cdefs.h>

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/ioccom.h>
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/tty.h>
#include <sys/file.h>

#if __FreeBSD_version >= 500014
#include <sys/selinfo.h>
#else
#include <sys/select.h>
#endif

#include <sys/sysctl.h>

#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>

#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include "usbdevs.h"

#include <dev/usb/ucomvar.h>

#include <dev/usb/uftdireg.h>

/* #define USB_DEBUG 1 /* */

#ifdef USB_DEBUG
static int uftdidebug = 22;
SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
	   &uftdidebug, 0, "uftdi debug level");
#define DPRINTF(x)      do { \
				if (uftdidebug) \
					logprintf x; \
			} while (0)

#define DPRINTFN(n, x)  do { \
				if (uftdidebug > (n)) \
					logprintf x; \
			} while (0)

#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif

#define UFTDI_CONFIG_INDEX	0
#define UFTDI_IFACE_INDEX	0


/*
 * These are the maximum number of bytes transferred per frame.
 * The output buffer size cannot be increased due to the size encoding.
 */
#define UFTDIIBUFSIZE 64
#define UFTDIOBUFSIZE 64

struct uftdi_softc {
	struct ucom_softc	sc_ucom;

	usbd_interface_handle	sc_iface;	/* interface */

	enum uftdi_type		sc_type;
	u_int			sc_hdrlen;

	u_char			sc_msr;
	u_char			sc_lsr;

	u_int			last_lcr;
};

Static void	uftdi_get_status(void *, int portno, u_char *lsr, u_char *msr);
Static void	uftdi_set(void *, int, int, int);
Static int	uftdi_param(void *, int, struct termios *);
Static int	uftdi_open(void *sc, int portno);
Static void	uftdi_read(void *sc, int portno, u_char **ptr,u_int32_t *count);
Static void	uftdi_write(void *sc, int portno, u_char *to, u_char *from,
			    u_int32_t *count);
Static void	uftdi_break(void *sc, int portno, int onoff);

struct ucom_callback uftdi_callback = {
	uftdi_get_status,
	uftdi_set,
	uftdi_param,
	NULL,
	uftdi_open,
	NULL,
	uftdi_read,
	uftdi_write,
};

USB_MATCH(uftdi)
{
	USB_MATCH_START(uftdi, uaa);

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

	DPRINTFN(20,("uftdi: vendor=0x%x, product=0x%x\n",
		     uaa->vendor, uaa->product));

	if (uaa->vendor == USB_VENDOR_FTDI &&
	    (uaa->product == USB_PRODUCT_FTDI_SERIAL_8U100AX ||
	     uaa->product == USB_PRODUCT_FTDI_SERIAL_8U232AM ||
	     uaa->product == USB_PRODUCT_FTDI_SEMC_DSS20 ||
	     uaa->product == USB_PRODUCT_FTDI_CFA_631 ||
	     uaa->product == USB_PRODUCT_FTDI_CFA_632 ||
	     uaa->product == USB_PRODUCT_FTDI_CFA_633 ||
	     uaa->product == USB_PRODUCT_FTDI_CFA_634 ||
	     uaa->product == USB_PRODUCT_FTDI_USBSERIAL ||
	     uaa->product == USB_PRODUCT_FTDI_MX2_3 ||
	     uaa->product == USB_PRODUCT_FTDI_MX4_5 ||
	     uaa->product == USB_PRODUCT_FTDI_LK202 ||
	     uaa->product == USB_PRODUCT_FTDI_LK204))
		return (UMATCH_VENDOR_PRODUCT);
	if (uaa->vendor == USB_VENDOR_SIIG2 &&
	    (uaa->product == USB_PRODUCT_SIIG2_US2308))
		return (UMATCH_VENDOR_PRODUCT);
	if (uaa->vendor == USB_VENDOR_INTREPIDCS &&
	    (uaa->product == USB_PRODUCT_INTREPIDCS_VALUECAN ||
	    uaa->product == USB_PRODUCT_INTREPIDCS_NEOVI))
		return (UMATCH_VENDOR_PRODUCT);
	/* UMTS: */
	if (uaa->vendor == USB_VENDOR_OPTIONNV &&
	    (uaa->product == USB_PRODUCT_OPTIONNV_QUADUMTS))
		return (UMATCH_VENDOR_PRODUCT);
	if (uaa->vendor == USB_VENDOR_OPTIONNV &&
	    (uaa->product == USB_PRODUCT_OPTIONNV_QUADUMTS2))
		return (UMATCH_VENDOR_PRODUCT);
	return (UMATCH_NONE);
}

USB_ATTACH(uftdi)
{
	USB_ATTACH_START(uftdi, sc, uaa);
	usbd_device_handle dev = uaa->device;
	usbd_interface_handle iface;
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	char *devinfo;
	const char *devname;
	int i;
	usbd_status err;
	struct ucom_softc *ucom = &sc->sc_ucom;
	DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc));
	devinfo = malloc(1024, M_USBDEV, M_WAITOK);

	ucom->sc_dev = self;
	ucom->sc_udev = dev;

	devname = USBDEVNAME(ucom->sc_dev);

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

	err = usbd_device2interface_handle(dev, UFTDI_IFACE_INDEX, &iface);
	if (err) {
		printf("\n%s: failed to get interface, err=%s\n",
		       devname, usbd_errstr(err));
		goto bad;
	}

	usbd_devinfo(dev, 0, devinfo);
	/*	USB_ATTACH_SETUP;*/
	printf("%s: %s\n", devname, devinfo);

	id = usbd_get_interface_descriptor(iface);
	ucom->sc_iface = iface;
	switch( uaa->vendor ){
	case USB_VENDOR_FTDI:
	case USB_VENDOR_OPTIONNV:		/* UMTS: */
		switch( uaa->product ){
		case USB_PRODUCT_FTDI_SERIAL_8U100AX:
		case USB_PRODUCT_OPTIONNV_QUADUMTS:	/* UMTS: */
		case USB_PRODUCT_OPTIONNV_QUADUMTS2:	/* UMTS: */
			sc->sc_type = UFTDI_TYPE_SIO;
			sc->sc_hdrlen = 1;
			break;
		case USB_PRODUCT_FTDI_SEMC_DSS20:
		case USB_PRODUCT_FTDI_SERIAL_8U232AM:
		case USB_PRODUCT_FTDI_CFA_631:
		case USB_PRODUCT_FTDI_CFA_632:
		case USB_PRODUCT_FTDI_CFA_633:
		case USB_PRODUCT_FTDI_CFA_634:
		case USB_PRODUCT_FTDI_USBSERIAL:
		case USB_PRODUCT_FTDI_MX2_3:
		case USB_PRODUCT_FTDI_MX4_5:
		case USB_PRODUCT_FTDI_LK202:
		case USB_PRODUCT_FTDI_LK204:
			sc->sc_type = UFTDI_TYPE_8U232AM;
			sc->sc_hdrlen = 0;
			break;

		default:		/* Can't happen */
			goto bad;
		}
		break;

	case USB_VENDOR_INTREPIDCS:
		switch( uaa->product ){
		case USB_PRODUCT_INTREPIDCS_VALUECAN:
		case USB_PRODUCT_INTREPIDCS_NEOVI:
			sc->sc_type = UFTDI_TYPE_8U232AM;
			sc->sc_hdrlen = 0;
			break;

		default:		/* Can't happen */
			goto bad;
		}
		break;

	case USB_VENDOR_SIIG2:
		switch( uaa->product ){
		case USB_PRODUCT_SIIG2_US2308:
			sc->sc_type = UFTDI_TYPE_8U232AM;
			sc->sc_hdrlen = 0;
			break;

		default:		/* Can't happen */
			goto bad;
		}
		break;

	default:		/* Can't happen */
		goto bad;
	}

	ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;

	printf("%s: id->bNumEndpoints %d\n", devname, id->bNumEndpoints); /* UMTS: */
	for (i = 0; i < id->bNumEndpoints; i++) {
		int addr, dir, attr;
		ed = usbd_interface2endpoint_descriptor(iface, i);
		if (ed == NULL) {
			printf("%s: could not read endpoint descriptor"
			       ": %s\n", devname, usbd_errstr(err));
			goto bad;
		}

		addr = ed->bEndpointAddress;
		dir = UE_GET_DIR(ed->bEndpointAddress);
		attr = ed->bmAttributes & UE_XFERTYPE;
		printf("%s: Endpoint %d addr 0x%x dir 0x%x attr 0x%x\n",
			devname, i, addr, dir, attr); /* UMTS: */
		if (dir == UE_DIR_IN && attr == UE_BULK)
		  ucom->sc_bulkin_no = addr;
		else if (dir == UE_DIR_OUT && attr == UE_BULK)
		  ucom->sc_bulkout_no = addr;
		/* UMTS: what to do with this one? */
		else if (dir == UE_DIR_IN && attr == UE_INTERRUPT) {
		  printf("%s: Endpoint %d attr UE_INTERRUPT, not registered\n", devname, i); /* UMTS: */
		}
		else {
		  printf("%s: unexpected endpoint\n", devname);
		  goto bad;
		}
	}
	if (ucom->sc_bulkin_no == -1) {
		printf("%s: Could not find data bulk in\n",
		       devname);
		goto bad;
	}
	if (ucom->sc_bulkout_no == -1) {
		printf("%s: Could not find data bulk out\n",
		       devname);
		goto bad;
	}
        ucom->sc_parent  = sc;
	ucom->sc_portno = 0; /* UMTS: Andrew: port number passed back into other fns??? */
	/* bulkin, bulkout set above */

  	ucom->sc_ibufsize = UFTDIIBUFSIZE;
	ucom->sc_obufsize = UFTDIOBUFSIZE; /* UMTS: Andrew - sc->sc_hdrlen; */
	ucom->sc_ibufsizepad = UFTDIIBUFSIZE;
	ucom->sc_opkthdrlen = 0; /* UMTS: Andrew: sc->sc_hdrlen; */


	ucom->sc_callback = &uftdi_callback;
#if 0
	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev,
			   USBDEV(ucom->sc_dev));
#endif
	DPRINTF(("uftdi: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no));
	ucom_attach(&sc->sc_ucom);
	free(devinfo, M_USBDEV);

	USB_ATTACH_SUCCESS_RETURN;

bad:
	DPRINTF(("uftdi_attach: ATTACH ERROR\n"));
	ucom->sc_dying = 1;
	free(devinfo, M_USBDEV);

	USB_ATTACH_ERROR_RETURN;
}
#if 0
int
uftdi_activate(device_ptr_t self, enum devact act)
{
	struct uftdi_softc *sc = (struct uftdi_softc *)self;
	int rv = 0;

	switch (act) {
	case DVACT_ACTIVATE:
		return (EOPNOTSUPP);

	case DVACT_DEACTIVATE:
		if (sc->sc_subdev != NULL)
			rv = config_deactivate(sc->sc_subdev);
		sc->sc_ucom.sc_dying = 1;
		break;
	}
	return (rv);
}
#endif
#if 1
USB_DETACH(uftdi)
{
	USB_DETACH_START(uftdi, sc);

	int rv = 0;

	DPRINTF(("uftdi_detach: sc=%p\n", sc));
	sc->sc_ucom.sc_dying = 1;
	rv = ucom_detach(&sc->sc_ucom);

	return rv;
}
#endif
Static int
uftdi_open(void *vsc, int portno)
{
	struct uftdi_softc *sc = vsc;
	struct ucom_softc *ucom = &sc->sc_ucom;
	usb_device_request_t req;
	usbd_status err;
	struct termios t;

	DPRINTF(("uftdi_open: sc=%p\n", sc));

	if (ucom->sc_dying)
		return (EIO);
	/* UMTS:
	   Andrew: we skip all the baud settings etc. here
	 */
	return (0);

	/* Perform a full reset on the device */
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_RESET;
	USETW(req.wValue, FTDI_SIO_RESET_SIO);
	USETW(req.wIndex, portno);
	USETW(req.wLength, 0);
	err = usbd_do_request(ucom->sc_udev, &req, NULL);
	if (err)
		return (EIO);

	/* Set 9600 baud, 2 stop bits, no parity, 8 bits */
	t.c_ospeed = 9600;
	t.c_cflag = CSTOPB | CS8;
	(void)uftdi_param(sc, portno, &t);

	/* Turn on RTS/CTS flow control */
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_SET_FLOW_CTRL;
	USETW(req.wValue, 0);
	USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, portno);
	USETW(req.wLength, 0);
	err = usbd_do_request(ucom->sc_udev, &req, NULL);
	if (err)
		return (EIO);

	return (0);
}

Static void
uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
{
	struct uftdi_softc *sc = vsc;
	u_char msr, lsr;

	DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno,
		     *count));

	/* UMTS:
	msr = FTDI_GET_MSR(*ptr);
	lsr = FTDI_GET_LSR(*ptr);
	*/

#ifdef USB_DEBUG
	if (*count != 2)
		DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]="
			    "0x%02x\n", sc, portno, *count, (*ptr)[2]));
#endif

	return;

	/* UMTS: Andrew says:
        Appears to get called with buffers full of data received
        from the device, with the option to remove headers or
        perform other processing.  For our device, it all passes
        straight through.
	*/

	if (sc->sc_msr != msr ||
	    (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
		DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
			 "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
			 lsr, sc->sc_lsr));
		sc->sc_msr = msr;
		sc->sc_lsr = lsr;
		ucom_status_change(&sc->sc_ucom);
	}

	/* Pick up status and adjust data part. */
	*ptr += 2;
	*count -= 2;
}

Static void
uftdi_write(void *vsc, int portno, u_char *to, u_char *from, u_int32_t *count)
{
	struct uftdi_softc *sc = vsc;

	DPRINTFN(10,("uftdi_write: sc=%p, port=%d count=%u data[0]=0x%02x\n",
		     vsc, portno, *count, from[0]));

	/* Make length tag and copy data */
	/* UMTS: Andrew says:
        Gets called with buffer of data to go to the device, with the
        opportunity to add headers etc.  We just copy it unchanged.
	*/
	memcpy(to, from, *count);
	return;

	if (sc->sc_hdrlen > 0)
		*to = FTDI_OUT_TAG(*count, portno);

	memcpy(to + sc->sc_hdrlen, from, *count);
	*count += sc->sc_hdrlen;
}

Static void
uftdi_set(void *vsc, int portno, int reg, int onoff)
{
	struct uftdi_softc *sc = vsc;
	struct ucom_softc *ucom = vsc;
	usb_device_request_t req;
	int ctl;

	DPRINTF(("uftdi_set: sc=%p, port=%d reg=%d onoff=%d\n", vsc, portno,
		 reg, onoff));

	switch (reg) {
	case UCOM_SET_DTR:
		ctl = onoff ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW;
		printf("uftdi: DTR %s\n", onoff ? "on" : "off"); /* UMTS: */
		break;
	case UCOM_SET_RTS:
		ctl = onoff ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW;
		printf("uftdi: RTS %s\n", onoff ? "on" : "off"); /* UMTS: */
		break;
	case UCOM_SET_BREAK:
		uftdi_break(sc, portno, onoff);
		printf("uftdi: BREAK %s\n", onoff ? "on" : "off"); /* UMTS: */
		return;
	default:
		return;
	}
	/* UMTS: Andrew skiped the rest */
	return;

	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_MODEM_CTRL;
	USETW(req.wValue, ctl);
	USETW(req.wIndex, portno);
	USETW(req.wLength, 0);
	DPRINTFN(2,("uftdi_set: reqtype=0x%02x req=0x%02x value=0x%04x "
		    "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest,
		    UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength)));
	(void)usbd_do_request(ucom->sc_udev, &req, NULL);
}

Static int
uftdi_param(void *vsc, int portno, struct termios *t)
{
	struct uftdi_softc *sc = vsc;
	struct ucom_softc *ucom = &sc->sc_ucom;
	usb_device_request_t req;
	usbd_status err;
	int rate=0, data, flow;

	DPRINTF(("uftdi_param: sc=%p\n", sc));

	if (ucom->sc_dying)
		return (EIO);
	/* UMTS: Adrew says:
	   Our device doesn't have any known means of baud/format control
	*/
	return (0);

	switch (sc->sc_type) {
	case UFTDI_TYPE_SIO:
		switch (t->c_ospeed) {
		case 300: rate = ftdi_sio_b300; break;
		case 600: rate = ftdi_sio_b600; break;
		case 1200: rate = ftdi_sio_b1200; break;
		case 2400: rate = ftdi_sio_b2400; break;
		case 4800: rate = ftdi_sio_b4800; break;
		case 9600: rate = ftdi_sio_b9600; break;
		case 19200: rate = ftdi_sio_b19200; break;
		case 38400: rate = ftdi_sio_b38400; break;
		case 57600: rate = ftdi_sio_b57600; break;
		case 115200: rate = ftdi_sio_b115200; break;
		default:
			return (EINVAL);
		}
		break;

	case UFTDI_TYPE_8U232AM:
		switch(t->c_ospeed) {
		case 300: rate = ftdi_8u232am_b300; break;
		case 600: rate = ftdi_8u232am_b600; break;
		case 1200: rate = ftdi_8u232am_b1200; break;
		case 2400: rate = ftdi_8u232am_b2400; break;
		case 4800: rate = ftdi_8u232am_b4800; break;
		case 9600: rate = ftdi_8u232am_b9600; break;
		case 19200: rate = ftdi_8u232am_b19200; break;
		case 38400: rate = ftdi_8u232am_b38400; break;
		case 57600: rate = ftdi_8u232am_b57600; break;
		case 115200: rate = ftdi_8u232am_b115200; break;
		case 230400: rate = ftdi_8u232am_b230400; break;
		case 460800: rate = ftdi_8u232am_b460800; break;
		case 921600: rate = ftdi_8u232am_b921600; break;
		case 2000000: rate = ftdi_8u232am_b2000000; break;
		case 3000000: rate = ftdi_8u232am_b3000000; break;
		default:
			return (EINVAL);
		}
		break;
	}
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_SET_BAUD_RATE;
	USETW(req.wValue, rate);
	USETW(req.wIndex, portno);
	USETW(req.wLength, 0);
	DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x "
		    "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest,
		    UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength)));
	err = usbd_do_request(ucom->sc_udev, &req, NULL);
	if (err)
		return (EIO);

	if (ISSET(t->c_cflag, CSTOPB))
		data = FTDI_SIO_SET_DATA_STOP_BITS_2;
	else
		data = FTDI_SIO_SET_DATA_STOP_BITS_1;
	if (ISSET(t->c_cflag, PARENB)) {
		if (ISSET(t->c_cflag, PARODD))
			data |= FTDI_SIO_SET_DATA_PARITY_ODD;
		else
			data |= FTDI_SIO_SET_DATA_PARITY_EVEN;
	} else
		data |= FTDI_SIO_SET_DATA_PARITY_NONE;
	switch (ISSET(t->c_cflag, CSIZE)) {
	case CS5:
		data |= FTDI_SIO_SET_DATA_BITS(5);
		break;
	case CS6:
		data |= FTDI_SIO_SET_DATA_BITS(6);
		break;
	case CS7:
		data |= FTDI_SIO_SET_DATA_BITS(7);
		break;
	case CS8:
		data |= FTDI_SIO_SET_DATA_BITS(8);
		break;
	}
	sc->last_lcr = data;

	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_SET_DATA;
	USETW(req.wValue, data);
	USETW(req.wIndex, portno);
	USETW(req.wLength, 0);
	DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x "
		    "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest,
		    UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength)));
	err = usbd_do_request(ucom->sc_udev, &req, NULL);
	if (err)
		return (EIO);

	if (ISSET(t->c_cflag, CRTSCTS)) {
		flow = FTDI_SIO_RTS_CTS_HS;
		USETW(req.wValue, 0);
	} else if (ISSET(t->c_iflag, IXON|IXOFF)) {
		flow = FTDI_SIO_XON_XOFF_HS;
		USETW2(req.wValue, t->c_cc[VSTOP], t->c_cc[VSTART]);
	} else {
		flow = FTDI_SIO_DISABLE_FLOW_CTRL;
		USETW(req.wValue, 0);
	}
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_SET_FLOW_CTRL;
	USETW2(req.wIndex, flow, portno);
	USETW(req.wLength, 0);
	err = usbd_do_request(ucom->sc_udev, &req, NULL);
	if (err)
		return (EIO);

	return (0);
}

void
uftdi_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
{
	struct uftdi_softc *sc = vsc;

	DPRINTF(("uftdi_status: msr=0x%02x lsr=0x%02x\n",
		 sc->sc_msr, sc->sc_lsr));
	/* UMTS: Andrew says:
        These are apparently supposed to reflect 16550 MSR/LSR registers.
        We don't have any of this status, so just return defaults.
	*/
	if (msr != NULL)
		*msr = 0; /* UMTS: sc->sc_msr; */
	if (lsr != NULL)
		*lsr = 0; /* UMTS: sc->sc_lsr; */
}

void
uftdi_break(void *vsc, int portno, int onoff)
{
	struct uftdi_softc *sc = vsc;
	struct ucom_softc *ucom = vsc;

	usb_device_request_t req;
	int data;

	DPRINTF(("uftdi_break: sc=%p, port=%d onoff=%d\n", vsc, portno,
		  onoff));
	/* UMTS: Andrew: */
	printf("uftdi: set break %s\n", onoff ? "active" : "off");
	return;

	if (onoff) {
		data = sc->last_lcr | FTDI_SIO_SET_BREAK;
	} else {
		data = sc->last_lcr;
	}

	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = FTDI_SIO_SET_DATA;
	USETW(req.wValue, data);
	USETW(req.wIndex, portno);
	USETW(req.wLength, 0);
	(void)usbd_do_request(ucom->sc_udev, &req, NULL);
}

Static device_method_t uftdi_methods[] = {
	/* Device interface */
	DEVMETHOD(device_probe, uftdi_match),
	DEVMETHOD(device_attach, uftdi_attach),
	DEVMETHOD(device_detach, uftdi_detach),

	{ 0, 0 }
};

Static driver_t uftdi_driver = {
	"ucom",
	uftdi_methods,
	sizeof (struct uftdi_softc)
};

DRIVER_MODULE(uftdi, uhub, uftdi_driver, ucom_devclass, usbd_driver_load, 0);
MODULE_DEPEND(uftdi, usb, 1, 1, 1);
MODULE_DEPEND(uftdi, ucom,UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
-------------- next part --------------

$Id: umts.txt,v 1.3 2005/10/27 06:29:20 guru Exp $

The hacked driver usb/uftdi (thanks to Andrew Gordon <arg at arg.me.uk>
for the idea and some nice details) now has support for the two
cards:

vendor=0x0af0 product=0x6300
vendor=0x0af0 product=0x6000

the changed kernel files are:

/usr/src/sys/dev/usb/usbdevs
/usr/src/sys/dev/usb/uftdi.c
/usr/src/sys/dev/usb/ucom.c

check for details;
an attach brings up in user land the device /dev/ucom0

details of the two tested cards:

product=0x6300 (used by the provider Vodafone in Germany):

FreeBSD Kermit>set line /dev/ucom0
FreeBSD Kermit>c
Connecting to /dev/ucom0, speed 9600

ati
Manufacturer: Option N.V.
Model: GlobeTrotter Fusion Quad Lite
Revision: 1.5.5  (Date: May 17 2005, Time: 14:55:44)
OK

may be it is this one:
http://www.option.com/products/fusionquad.shtml

product=0x6000 (used by the provider German T-Com):

ati2
Manufacturer: Option N.V.
Model: GlobeTrotter Fusion
Revision: 2.2.1dnp   (Date: Sep 13 2004, Time: 11:15:47)

OK

the PPPD daemon is a bit outdated and tricky on FreeBSD and can't deduce the
remote peers addr:
	...
sent [IPCP ConfNak id=0x4a <addr 0.0.0.0>]
rcvd [IPCP ConfNak id=0x5 <addr 10.227.149.188>]
sent [IPCP ConfReq id=0x6 <addr 10.227.149.188>]
rcvd [IPCP ConfReq id=0x4b]
sent [IPCP ConfAck id=0x4b]
rcvd [IPCP ConfAck id=0x6 <addr 10.227.149.188>]
Could not determine remote IP address
sent [IPCP TermReq id=0x7 "Could not determine remote IP address"]

on Linux they seem to deduce the remote addr simply from the
local one:

sent [IPCP ConfReq id=0x5 <addr 10.227.222.211> <ms-dns1 139.7.30.125> <ms-dns3 139.7.30.126>]
rcvd [IPCP ConfAck id=0x5 <addr 10.227.222.211> <ms-dns1 139.7.30.125> <ms-dns3 139.7.30.126>]
rcvd [IPCP ConfReq id=0x5]
sent [IPCP ConfAck id=0x5]
Could not determine remote IP address: defaulting to 10.64.64.64
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
local  IP address 10.227.222.211
remote IP address 10.64.64.64
primary   DNS address 139.7.30.125
secondary DNS address 139.7.30.126

the line in /etc/ppp/peers/umts:
    noipdefault
    :10.64.64.64
helps him out, but this is a dirty trick I think (XXX)

btw: the pppd 2.4.3 simple has this code extended:
    if (ho->hisaddr == 0) {
        ho->hisaddr = htonl(0x0a404040 + ifunit);
        warn("Could not determine remote IP address: defaulting to %I",
             ho->hisaddr);
    }

FreeBSD comes with pppd-2.3.11; the version 2.4.x is not ported
to FreeBSD;


the launch of PPP is:

# /usr/local/sbin/pppd call umts

with these two files (the line +--------------+ does not belong to the
file itself):

/etc/ppp/chat-umts:

+----------------------------------------------------------------+

'' AT
OK at_opsys=1,2
#
# we can not send down the PIN twice, it gives 'ERROR' 2nd time
# how we can logout the SIM from UMTS?
#
OK at+cpin="xxxxxxx"
'' AT+CGDCONT=1,"IP","web.vodafone.de"
OK ATD*99***1#
'CONNECT 384000'
+----------------------------------------------------------------+

/etc/ppp/peers/umts:

+----------------------------------------------------------------+
ucom0 230400 crtscts
connect '/usr/bin/chat -v -f /etc/ppp/chat-umts ; \
         sleep 5'
name UMTS_CHAP_SRVR
noipdefault
:10.64.64.64
novj
noccp
defaultroute
ipcp-max-configure 20
ipcp-max-failure 20
ipcp-max-terminate 20
ipcp-accept-local
ipcp-accept-remote
usepeerdns
+----------------------------------------------------------------+




I've send this e-mail to the manufactur, they replied that they
can't give me more information without having a 'project' to
work on this (read: the chance to earn money):

Hello,
Vodafone in Germany send me a PCMCIA card which says about itself:
ati
Manufacturer: Option N.V.
Model: GlobeTrotter Fusion Quad Lite
Revision: 1.5.5  (Date: May 17 2005, Time: 14:55:44)
OK
and I'm writing an USB based device driver to get the card working
in the operating system FreeBSD 5.4. The driver is already working
fine and I can subscribe perfectly to UMTS. I'ld like to have a look
in some technical specification of the this card to clear-up some
questions I still have in my driver, for example how to use the
3rd endpoint, the inerrupt driven one, the card provides? Please
contact me by e-mail so that I could give more information and
details about this work: <guru at Sisis.de>
Thanks in advance and kind regards, Matthias


Subject: RE: Option Support Web Form
Date: Mon, 3 Oct 2005 17:49:38 +0200
From: "Support at Option" <Support at option.com>
To: <guru at Sisis.de>
 
Dear Sir,
 
The card you have purchased is a Vodafone card, normally Vodafone should
provide the necessary support. I understand Vodafone may not know all
necessary information and we do not have a simple single document we can
provide regarding this interface. This being said in the newest Linux
kernel is a fully functional driver for this type of card. The sources
are available for this driver and you can have a look at them to find
out how this driver works. In the scope of a sufficiently big enough
project our engineers may be able to answer more specific questions
regarding this card. Of course, complicated questions will require a
bigger project in order to justify the necessary resources to answer
your question. I hope you understand our point of view in this.
 
Best regards,

-------------- next part --------------
340d339
< vendor OPTIONNV		0x0af0	Option N.V.
541d539
< product CANON EOS300D		0x3084	EOS 300D / Digital Rebel
1069,1072d1066
< 
< /* Option N.V. */
< product OPTIONNV QUADUMTS2	0x6000	GlobeTrotter Fusion Quad Lite UMTS/GPRS
< product OPTIONNV QUADUMTS	0x6300	GlobeTrotter Fusion Quad Lite 3D


More information about the freebsd-mobile mailing list