device features.
*/
-#define DRIVER_VERSION "v0.7.1"
+#define DRIVER_VERSION "v0.7.2"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
#define NOVATELWIRELESS_PRODUCT_EMBEDDED_2 0x8001
#define NOVATELWIRELESS_PRODUCT_GLOBAL_2 0x9001
+/* AMOI PRODUCTS */
+#define AMOI_VENDOR_ID 0x1614
+#define AMOI_PRODUCT_H01 0x0800
+#define AMOI_PRODUCT_H01A 0x7002
+#define AMOI_PRODUCT_H02 0x0802
+
#define DELL_VENDOR_ID 0x413C
#define KYOCERA_VENDOR_ID 0x0c88
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_2) }, /* Novatel Embedded product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_2) }, /* Novatel Global product */
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
+
{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
.description = "GSM modem (1-port)",
.usb_driver = &option_driver,
.id_table = option_ids,
- .num_interrupt_in = NUM_DONT_CARE,
- .num_bulk_in = NUM_DONT_CARE,
- .num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
.open = option_open,
.close = option_close,
static void option_rx_throttle(struct usb_serial_port *port)
{
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
}
static void option_rx_unthrottle(struct usb_serial_port *port)
{
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
}
static void option_break_ctl(struct usb_serial_port *port, int break_state)
{
/* Unfortunately, I don't know how to send a break */
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
}
static void option_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios)
{
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* Doesn't support option setting */
tty_termios_copy_hw(port->tty->termios, old_termios);
option_send_setup(port);
portdata = usb_get_serial_port_data(port);
+ /* FIXME: what locks portdata fields ? */
if (set & TIOCM_RTS)
portdata->rts_state = 1;
if (set & TIOCM_DTR)
portdata = usb_get_serial_port_data(port);
- dbg("%s: write (%d chars)", __FUNCTION__, count);
+ dbg("%s: write (%d chars)", __func__, count);
i = 0;
left = count;
dbg("usb_write %p failed (err=%d)",
this_urb, this_urb->status);
- dbg("%s: endpoint %d buf %d", __FUNCTION__,
+ dbg("%s: endpoint %d buf %d", __func__,
usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
}
count -= left;
- dbg("%s: wrote (did %d)", __FUNCTION__, count);
+ dbg("%s: wrote (did %d)", __func__, count);
return count;
}
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s: %p", __FUNCTION__, urb);
+ dbg("%s: %p", __func__, urb);
endpoint = usb_pipeendpoint(urb->pipe);
- port = (struct usb_serial_port *) urb->context;
+ port = urb->context;
if (status) {
dbg("%s: nonzero status: %d on endpoint %02x.",
- __FUNCTION__, status, endpoint);
+ __func__, status, endpoint);
} else {
tty = port->tty;
if (urb->actual_length) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
} else {
- dbg("%s: empty read urb received", __FUNCTION__);
+ dbg("%s: empty read urb received", __func__);
}
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
printk(KERN_ERR "%s: resubmit read urb failed. "
- "(%d)", __FUNCTION__, err);
+ "(%d)", __func__, err);
}
}
return;
struct option_port_private *portdata;
int i;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
- port = (struct usb_serial_port *) urb->context;
+ port = urb->context;
usb_serial_port_softint(port);
{
int err;
int status = urb->status;
- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct usb_serial_port *port = urb->context;
struct option_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
- dbg("%s", __FUNCTION__);
- dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
+ dbg("%s", __func__);
+ dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
if (status == 0) {
struct usb_ctrlrequest *req_pkt =
(struct usb_ctrlrequest *)urb->transfer_buffer;
if (!req_pkt) {
- dbg("%s: NULL req_pkt\n", __FUNCTION__);
+ dbg("%s: NULL req_pkt\n", __func__);
return;
}
if ((req_pkt->bRequestType == 0xA1) &&
urb->transfer_buffer +
sizeof(struct usb_ctrlrequest));
- dbg("%s: signal x%x", __FUNCTION__, signals);
+ dbg("%s: signal x%x", __func__, signals);
old_dcd_state = portdata->dcd_state;
portdata->cts_state = 1;
old_dcd_state && !portdata->dcd_state)
tty_hangup(port->tty);
} else {
- dbg("%s: type %x req %x", __FUNCTION__,
+ dbg("%s: type %x req %x", __func__,
req_pkt->bRequestType,req_pkt->bRequest);
}
} else
- dbg("%s: error %d", __FUNCTION__, status);
+ dbg("%s: error %d", __func__, status);
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
dbg("%s: resubmit intr urb failed. (%d)",
- __FUNCTION__, err);
+ __func__, err);
}
}
portdata = usb_get_serial_port_data(port);
+
for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
if (this_urb && !test_bit(i, &portdata->out_busy))
data_len += OUT_BUFLEN;
}
- dbg("%s: %d", __FUNCTION__, data_len);
+ dbg("%s: %d", __func__, data_len);
return data_len;
}
for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
+ /* FIXME: This locking is insufficient as this_urb may
+ go unused during the test */
if (this_urb && test_bit(i, &portdata->out_busy))
data_len += this_urb->transfer_buffer_length;
}
- dbg("%s: %d", __FUNCTION__, data_len);
+ dbg("%s: %d", __func__, data_len);
return data_len;
}
portdata = usb_get_serial_port_data(port);
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* Set some sane defaults */
portdata->rts_state = 1;
if (! urb)
continue;
if (urb->dev != serial->dev) {
- dbg("%s: dev %p != %p", __FUNCTION__,
+ dbg("%s: dev %p != %p", __func__,
urb->dev, serial->dev);
continue;
}
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
dbg("%s: submit urb %d failed (%d) %d",
- __FUNCTION__, i, err,
+ __func__, i, err,
urb->transfer_buffer_length);
}
}
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
portdata->rts_state = 0;
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
- dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
+ dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
return NULL;
}
struct usb_serial_port *port;
struct option_port_private *portdata;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
}
}
+
+/** send RTS/DTR state to the port.
+ *
+ * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
+ * CDC.
+*/
static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
-
- dbg("%s", __FUNCTION__);
-
- if (port->number != 0)
- return 0;
+ int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ 0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
}
return 0;
struct option_port_private *portdata;
u8 *buffer;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
dbg("%s: kmalloc for option_port_private (%d) failed!.",
- __FUNCTION__, i);
+ __func__, i);
return (1);
}
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
dbg("%s: submit irq_in urb failed %d",
- __FUNCTION__, err);
+ __func__, err);
}
option_setup_urbs(serial);
struct usb_serial_port *port;
struct option_port_private *portdata;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* Stop reading/writing urbs */
for (i = 0; i < serial->num_ports; ++i) {