Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * IPWireless 3G UMTS TDD Modem driver (USB connected)
0004  *
0005  *   Copyright (C) 2004 Roelf Diedericks <roelfd@inet.co.za>
0006  *   Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
0007  *
0008  * All information about the device was acquired using SnoopyPro
0009  * on MSFT's O/S, and examing the MSFT drivers' debug output
0010  * (insanely left _on_ in the enduser version)
0011  *
0012  * It was written out of frustration with the IPWireless USB modem
0013  * supplied by Axity3G/Sentech South Africa not supporting
0014  * Linux whatsoever.
0015  *
0016  * Nobody provided any proprietary information that was not already
0017  * available for this device.
0018  *
0019  * The modem adheres to the "3GPP TS  27.007 AT command set for 3G
0020  * User Equipment (UE)" standard, available from
0021  * http://www.3gpp.org/ftp/Specs/html-info/27007.htm
0022  *
0023  * The code was only tested the IPWireless handheld modem distributed
0024  * in South Africa by Sentech.
0025  *
0026  * It may work for Woosh Inc in .nz too, as it appears they use the
0027  * same kit.
0028  *
0029  * There is still some work to be done in terms of handling
0030  * DCD, DTR, RTS, CTS which are currently faked.
0031  * It's good enough for PPP at this point. It's based off all kinds of
0032  * code found in usb/serial and usb/class
0033  */
0034 
0035 #include <linux/kernel.h>
0036 #include <linux/errno.h>
0037 #include <linux/slab.h>
0038 #include <linux/tty.h>
0039 #include <linux/tty_flip.h>
0040 #include <linux/module.h>
0041 #include <linux/spinlock.h>
0042 #include <linux/usb.h>
0043 #include <linux/usb/serial.h>
0044 #include <linux/uaccess.h>
0045 #include "usb-wwan.h"
0046 
0047 #define DRIVER_AUTHOR   "Roelf Diedericks"
0048 #define DRIVER_DESC "IPWireless tty driver"
0049 
0050 #define IPW_TTY_MAJOR   240 /* real device node major id, experimental range */
0051 #define IPW_TTY_MINORS  256 /* we support 256 devices, dunno why, it'd be insane :) */
0052 
0053 #define USB_IPW_MAGIC   0x6d02  /* magic number for ipw struct */
0054 
0055 
0056 /* Message sizes */
0057 #define EVENT_BUFFER_SIZE   0xFF
0058 #define CHAR2INT16(c1, c0)  (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
0059 
0060 /* vendor/product pairs that are known work with this driver*/
0061 #define IPW_VID     0x0bc3
0062 #define IPW_PID     0x0001
0063 
0064 
0065 /* Vendor commands: */
0066 
0067 /* baud rates */
0068 enum {
0069     ipw_sio_b256000 = 0x000e,
0070     ipw_sio_b128000 = 0x001d,
0071     ipw_sio_b115200 = 0x0020,
0072     ipw_sio_b57600  = 0x0040,
0073     ipw_sio_b56000  = 0x0042,
0074     ipw_sio_b38400  = 0x0060,
0075     ipw_sio_b19200  = 0x00c0,
0076     ipw_sio_b14400  = 0x0100,
0077     ipw_sio_b9600   = 0x0180,
0078     ipw_sio_b4800   = 0x0300,
0079     ipw_sio_b2400   = 0x0600,
0080     ipw_sio_b1200   = 0x0c00,
0081     ipw_sio_b600    = 0x1800
0082 };
0083 
0084 /* data bits */
0085 #define ipw_dtb_7       0x700
0086 #define ipw_dtb_8       0x810   /* ok so the define is misleading, I know, but forces 8,n,1 */
0087                     /* I mean, is there a point to any other setting these days? :) */
0088 
0089 /* usb control request types : */
0090 #define IPW_SIO_RXCTL       0x00    /* control bulk rx channel transmissions, value=1/0 (on/off) */
0091 #define IPW_SIO_SET_BAUD    0x01    /* set baud, value=requested ipw_sio_bxxxx */
0092 #define IPW_SIO_SET_LINE    0x03    /* set databits, parity. value=ipw_dtb_x */
0093 #define IPW_SIO_SET_PIN     0x03    /* set/clear dtr/rts value=ipw_pin_xxx */
0094 #define IPW_SIO_POLL        0x08    /* get serial port status byte, call with value=0 */
0095 #define IPW_SIO_INIT        0x11    /* initializes ? value=0 (appears as first thing todo on open) */
0096 #define IPW_SIO_PURGE       0x12    /* purge all transmissions?, call with value=numchar_to_purge */
0097 #define IPW_SIO_HANDFLOW    0x13    /* set xon/xoff limits value=0, and a buffer of 0x10 bytes */
0098 #define IPW_SIO_SETCHARS    0x13    /* set the flowcontrol special chars, value=0, buf=6 bytes, */
0099                     /* last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 */
0100 
0101 /* values used for request IPW_SIO_SET_PIN */
0102 #define IPW_PIN_SETDTR      0x101
0103 #define IPW_PIN_SETRTS      0x202
0104 #define IPW_PIN_CLRDTR      0x100
0105 #define IPW_PIN_CLRRTS      0x200 /* unconfirmed */
0106 
0107 /* values used for request IPW_SIO_RXCTL */
0108 #define IPW_RXBULK_ON       1
0109 #define IPW_RXBULK_OFF      0
0110 
0111 /* various 16 byte hardcoded transferbuffers used by flow control */
0112 #define IPW_BYTES_FLOWINIT  { 0x01, 0, 0, 0, 0x40, 0, 0, 0, \
0113                     0, 0, 0, 0, 0, 0, 0, 0 }
0114 
0115 /* Interpretation of modem status lines */
0116 /* These need sorting out by individually connecting pins and checking
0117  * results. FIXME!
0118  * When data is being sent we see 0x30 in the lower byte; this must
0119  * contain DSR and CTS ...
0120  */
0121 #define IPW_DSR         ((1<<4) | (1<<5))
0122 #define IPW_CTS         ((1<<5) | (1<<4))
0123 
0124 #define IPW_WANTS_TO_SEND   0x30
0125 
0126 static const struct usb_device_id id_table[] = {
0127     { USB_DEVICE(IPW_VID, IPW_PID) },
0128     { },
0129 };
0130 MODULE_DEVICE_TABLE(usb, id_table);
0131 
0132 static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
0133 {
0134     struct usb_device *udev = port->serial->dev;
0135     struct device *dev = &port->dev;
0136     u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT;
0137     u8 *buf_flow_init;
0138     int result;
0139 
0140     buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
0141     if (!buf_flow_init)
0142         return -ENOMEM;
0143 
0144     /* --1: Tell the modem to initialize (we think) From sniffs this is
0145      *  always the first thing that gets sent to the modem during
0146      *  opening of the device */
0147     dev_dbg(dev, "%s: Sending SIO_INIT (we guess)\n", __func__);
0148     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0149              IPW_SIO_INIT,
0150              USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0151              0,
0152              0, /* index */
0153              NULL,
0154              0,
0155              100000);
0156     if (result < 0)
0157         dev_err(dev, "Init of modem failed (error = %d)\n", result);
0158 
0159     /* reset the bulk pipes */
0160     usb_clear_halt(udev, usb_rcvbulkpipe(udev, port->bulk_in_endpointAddress));
0161     usb_clear_halt(udev, usb_sndbulkpipe(udev, port->bulk_out_endpointAddress));
0162 
0163     /*--2: Start reading from the device */
0164     dev_dbg(dev, "%s: setting up bulk read callback\n", __func__);
0165     usb_wwan_open(tty, port);
0166 
0167     /*--3: Tell the modem to open the floodgates on the rx bulk channel */
0168     dev_dbg(dev, "%s:asking modem for RxRead (RXBULK_ON)\n", __func__);
0169     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0170              IPW_SIO_RXCTL,
0171              USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0172              IPW_RXBULK_ON,
0173              0, /* index */
0174              NULL,
0175              0,
0176              100000);
0177     if (result < 0)
0178         dev_err(dev, "Enabling bulk RxRead failed (error = %d)\n", result);
0179 
0180     /*--4: setup the initial flowcontrol */
0181     dev_dbg(dev, "%s:setting init flowcontrol (%s)\n", __func__, buf_flow_init);
0182     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0183              IPW_SIO_HANDFLOW,
0184              USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0185              0,
0186              0,
0187              buf_flow_init,
0188              0x10,
0189              200000);
0190     if (result < 0)
0191         dev_err(dev, "initial flowcontrol failed (error = %d)\n", result);
0192 
0193     kfree(buf_flow_init);
0194     return 0;
0195 }
0196 
0197 static int ipw_attach(struct usb_serial *serial)
0198 {
0199     struct usb_wwan_intf_private *data;
0200 
0201     data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
0202     if (!data)
0203         return -ENOMEM;
0204 
0205     spin_lock_init(&data->susp_lock);
0206     usb_set_serial_data(serial, data);
0207     return 0;
0208 }
0209 
0210 static void ipw_release(struct usb_serial *serial)
0211 {
0212     struct usb_wwan_intf_private *data = usb_get_serial_data(serial);
0213 
0214     usb_set_serial_data(serial, NULL);
0215     kfree(data);
0216 }
0217 
0218 static void ipw_dtr_rts(struct usb_serial_port *port, int on)
0219 {
0220     struct usb_device *udev = port->serial->dev;
0221     struct device *dev = &port->dev;
0222     int result;
0223 
0224     dev_dbg(dev, "%s: on = %d\n", __func__, on);
0225 
0226     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0227              IPW_SIO_SET_PIN,
0228              USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0229              on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
0230              0,
0231              NULL,
0232              0,
0233              200000);
0234     if (result < 0)
0235         dev_err(dev, "setting dtr failed (error = %d)\n", result);
0236 
0237     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0238              IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
0239                     USB_RECIP_INTERFACE | USB_DIR_OUT,
0240              on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
0241              0,
0242              NULL,
0243              0,
0244              200000);
0245     if (result < 0)
0246         dev_err(dev, "setting rts failed (error = %d)\n", result);
0247 }
0248 
0249 static void ipw_close(struct usb_serial_port *port)
0250 {
0251     struct usb_device *udev = port->serial->dev;
0252     struct device *dev = &port->dev;
0253     int result;
0254 
0255     /*--3: purge */
0256     dev_dbg(dev, "%s:sending purge\n", __func__);
0257     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0258              IPW_SIO_PURGE, USB_TYPE_VENDOR |
0259                     USB_RECIP_INTERFACE | USB_DIR_OUT,
0260              0x03,
0261              0,
0262              NULL,
0263              0,
0264              200000);
0265     if (result < 0)
0266         dev_err(dev, "purge failed (error = %d)\n", result);
0267 
0268 
0269     /* send RXBULK_off (tell modem to stop transmitting bulk data on
0270        rx chan) */
0271     result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0272              IPW_SIO_RXCTL,
0273              USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
0274              IPW_RXBULK_OFF,
0275              0, /* index */
0276              NULL,
0277              0,
0278              100000);
0279 
0280     if (result < 0)
0281         dev_err(dev, "Disabling bulk RxRead failed (error = %d)\n", result);
0282 
0283     usb_wwan_close(port);
0284 }
0285 
0286 static struct usb_serial_driver ipw_device = {
0287     .driver = {
0288         .owner =    THIS_MODULE,
0289         .name =     "ipw",
0290     },
0291     .description =      "IPWireless converter",
0292     .id_table =     id_table,
0293     .num_ports =        1,
0294     .open =         ipw_open,
0295     .close =        ipw_close,
0296     .attach =       ipw_attach,
0297     .release =      ipw_release,
0298     .port_probe =       usb_wwan_port_probe,
0299     .port_remove =      usb_wwan_port_remove,
0300     .dtr_rts =      ipw_dtr_rts,
0301     .write =        usb_wwan_write,
0302 };
0303 
0304 static struct usb_serial_driver * const serial_drivers[] = {
0305     &ipw_device, NULL
0306 };
0307 
0308 module_usb_serial_driver(serial_drivers, id_table);
0309 
0310 /* Module information */
0311 MODULE_AUTHOR(DRIVER_AUTHOR);
0312 MODULE_DESCRIPTION(DRIVER_DESC);
0313 MODULE_LICENSE("GPL");