| .. | .. |
|---|
| 132 | 132 | } |
|---|
| 133 | 133 | EXPORT_SYMBOL(usb_wwan_tiocmset); |
|---|
| 134 | 134 | |
|---|
| 135 | | -static int get_serial_info(struct usb_serial_port *port, |
|---|
| 136 | | - struct serial_struct __user *retinfo) |
|---|
| 135 | +int usb_wwan_get_serial_info(struct tty_struct *tty, |
|---|
| 136 | + struct serial_struct *ss) |
|---|
| 137 | 137 | { |
|---|
| 138 | | - struct serial_struct tmp; |
|---|
| 138 | + struct usb_serial_port *port = tty->driver_data; |
|---|
| 139 | 139 | |
|---|
| 140 | | - memset(&tmp, 0, sizeof(tmp)); |
|---|
| 141 | | - tmp.line = port->minor; |
|---|
| 142 | | - tmp.port = port->port_number; |
|---|
| 143 | | - tmp.baud_base = tty_get_baud_rate(port->port.tty); |
|---|
| 144 | | - tmp.close_delay = port->port.close_delay / 10; |
|---|
| 145 | | - tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
|---|
| 140 | + ss->line = port->minor; |
|---|
| 141 | + ss->port = port->port_number; |
|---|
| 142 | + ss->baud_base = tty_get_baud_rate(port->port.tty); |
|---|
| 143 | + ss->close_delay = port->port.close_delay / 10; |
|---|
| 144 | + ss->closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
|---|
| 146 | 145 | ASYNC_CLOSING_WAIT_NONE : |
|---|
| 147 | 146 | port->port.closing_wait / 10; |
|---|
| 148 | | - |
|---|
| 149 | | - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) |
|---|
| 150 | | - return -EFAULT; |
|---|
| 151 | 147 | return 0; |
|---|
| 152 | 148 | } |
|---|
| 149 | +EXPORT_SYMBOL(usb_wwan_get_serial_info); |
|---|
| 153 | 150 | |
|---|
| 154 | | -static int set_serial_info(struct usb_serial_port *port, |
|---|
| 155 | | - struct serial_struct __user *newinfo) |
|---|
| 151 | +int usb_wwan_set_serial_info(struct tty_struct *tty, |
|---|
| 152 | + struct serial_struct *ss) |
|---|
| 156 | 153 | { |
|---|
| 157 | | - struct serial_struct new_serial; |
|---|
| 154 | + struct usb_serial_port *port = tty->driver_data; |
|---|
| 158 | 155 | unsigned int closing_wait, close_delay; |
|---|
| 159 | 156 | int retval = 0; |
|---|
| 160 | 157 | |
|---|
| 161 | | - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) |
|---|
| 162 | | - return -EFAULT; |
|---|
| 163 | | - |
|---|
| 164 | | - close_delay = new_serial.close_delay * 10; |
|---|
| 165 | | - closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
|---|
| 166 | | - ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; |
|---|
| 158 | + close_delay = ss->close_delay * 10; |
|---|
| 159 | + closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
|---|
| 160 | + ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10; |
|---|
| 167 | 161 | |
|---|
| 168 | 162 | mutex_lock(&port->port.mutex); |
|---|
| 169 | 163 | |
|---|
| .. | .. |
|---|
| 181 | 175 | mutex_unlock(&port->port.mutex); |
|---|
| 182 | 176 | return retval; |
|---|
| 183 | 177 | } |
|---|
| 184 | | - |
|---|
| 185 | | -int usb_wwan_ioctl(struct tty_struct *tty, |
|---|
| 186 | | - unsigned int cmd, unsigned long arg) |
|---|
| 187 | | -{ |
|---|
| 188 | | - struct usb_serial_port *port = tty->driver_data; |
|---|
| 189 | | - |
|---|
| 190 | | - dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); |
|---|
| 191 | | - |
|---|
| 192 | | - switch (cmd) { |
|---|
| 193 | | - case TIOCGSERIAL: |
|---|
| 194 | | - return get_serial_info(port, |
|---|
| 195 | | - (struct serial_struct __user *) arg); |
|---|
| 196 | | - case TIOCSSERIAL: |
|---|
| 197 | | - return set_serial_info(port, |
|---|
| 198 | | - (struct serial_struct __user *) arg); |
|---|
| 199 | | - default: |
|---|
| 200 | | - break; |
|---|
| 201 | | - } |
|---|
| 202 | | - |
|---|
| 203 | | - dev_dbg(&port->dev, "%s arg not supported\n", __func__); |
|---|
| 204 | | - |
|---|
| 205 | | - return -ENOIOCTLCMD; |
|---|
| 206 | | -} |
|---|
| 207 | | -EXPORT_SYMBOL(usb_wwan_ioctl); |
|---|
| 178 | +EXPORT_SYMBOL(usb_wwan_set_serial_info); |
|---|
| 208 | 179 | |
|---|
| 209 | 180 | int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, |
|---|
| 210 | 181 | const unsigned char *buf, int count) |
|---|
| .. | .. |
|---|
| 299 | 270 | if (status) { |
|---|
| 300 | 271 | dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n", |
|---|
| 301 | 272 | __func__, status, endpoint); |
|---|
| 302 | | - |
|---|
| 303 | | - /* don't resubmit on fatal errors */ |
|---|
| 304 | | - if (status == -ESHUTDOWN || status == -ENOENT) |
|---|
| 273 | + if (status == -ESHUTDOWN || status == -ENOENT || status == -EPROTO) |
|---|
| 305 | 274 | return; |
|---|
| 306 | 275 | } else { |
|---|
| 307 | 276 | if (urb->actual_length) { |
|---|
| .. | .. |
|---|
| 494 | 463 | void (*callback) (struct urb *)) |
|---|
| 495 | 464 | { |
|---|
| 496 | 465 | struct usb_serial *serial = port->serial; |
|---|
| 497 | | - struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); |
|---|
| 498 | 466 | struct urb *urb; |
|---|
| 499 | | - struct usb_device_descriptor *desc = &serial->dev->descriptor; |
|---|
| 500 | 467 | |
|---|
| 501 | 468 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ |
|---|
| 502 | 469 | if (!urb) |
|---|
| .. | .. |
|---|
| 506 | 473 | usb_sndbulkpipe(serial->dev, endpoint) | dir, |
|---|
| 507 | 474 | buf, len, callback, ctx); |
|---|
| 508 | 475 | |
|---|
| 509 | | - if (intfdata->use_zlp && dir == USB_DIR_OUT) |
|---|
| 510 | | - urb->transfer_flags |= URB_ZERO_PACKET; |
|---|
| 511 | | - |
|---|
| 476 | +#if 1 //Added by Quectel for Zero Packet |
|---|
| 512 | 477 | if (dir == USB_DIR_OUT) { |
|---|
| 513 | | - if ((desc->idVendor == cpu_to_le16(0x1286) && |
|---|
| 514 | | - desc->idProduct == cpu_to_le16(0x4e3c))) |
|---|
| 478 | + if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) |
|---|
| 479 | + urb->transfer_flags |= URB_ZERO_PACKET; |
|---|
| 480 | + if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) |
|---|
| 481 | + urb->transfer_flags |= URB_ZERO_PACKET; |
|---|
| 482 | + if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) |
|---|
| 483 | + urb->transfer_flags |= URB_ZERO_PACKET; |
|---|
| 484 | + if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) |
|---|
| 515 | 485 | urb->transfer_flags |= URB_ZERO_PACKET; |
|---|
| 516 | 486 | } |
|---|
| 487 | +#endif |
|---|
| 488 | + |
|---|
| 517 | 489 | return urb; |
|---|
| 518 | 490 | } |
|---|
| 519 | 491 | |
|---|