Commit f5ee0557 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-serial-4.4-rc1' of...

Merge tag 'usb-serial-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

USB-serial updates for v4.4-rc1

These updates generalise the option DTR/RTS handling so that all
usb-wwan-based drivers can use it. This is specifically needed by some
Sierra modems, which can now all be handled by qcserial again.

Included are also some clean ups of the io_ti firmware handling.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parents 9e43643b 92944c45
...@@ -54,8 +54,10 @@ ...@@ -54,8 +54,10 @@
#define TI_MODE_CONFIGURING 0 /* Device has not entered start device */ #define TI_MODE_CONFIGURING 0 /* Device has not entered start device */
#define TI_MODE_BOOT 1 /* Staying in boot mode */ #define TI_MODE_BOOT 1 /* Staying in boot mode */
#define TI_MODE_DOWNLOAD 2 /* Made it to download mode */ #define TI_MODE_DOWNLOAD 2 /* Made it to download mode */
#define TI_MODE_TRANSITIONING 3 /* Currently in boot mode but #define TI_MODE_TRANSITIONING 3 /*
transitioning to download mode */ * Currently in boot mode but
* transitioning to download mode
*/
/* read urb state */ /* read urb state */
#define EDGE_READ_URB_RUNNING 0 #define EDGE_READ_URB_RUNNING 0
...@@ -97,9 +99,11 @@ struct edgeport_port { ...@@ -97,9 +99,11 @@ struct edgeport_port {
__u8 shadow_mcr; __u8 shadow_mcr;
__u8 shadow_lsr; __u8 shadow_lsr;
__u8 lsr_mask; __u8 lsr_mask;
__u32 ump_read_timeout; /* Number of milliseconds the UMP will __u32 ump_read_timeout; /*
wait without data before completing * Number of milliseconds the UMP will
a read short */ * wait without data before completing
* a read short
*/
int baud_rate; int baud_rate;
int close_pending; int close_pending;
int lsr_event; int lsr_event;
...@@ -115,8 +119,10 @@ struct edgeport_port { ...@@ -115,8 +119,10 @@ struct edgeport_port {
struct edgeport_serial { struct edgeport_serial {
struct product_info product_info; struct product_info product_info;
u8 TI_I2C_Type; /* Type of I2C in UMP */ u8 TI_I2C_Type; /* Type of I2C in UMP */
u8 TiReadI2C; /* Set to TRUE if we have read the u8 TiReadI2C; /*
I2c in Boot Mode */ * Set to TRUE if we have read the
* I2c in Boot Mode
*/
struct mutex es_lock; struct mutex es_lock;
int num_ports_open; int num_ports_open;
struct usb_serial *serial; struct usb_serial *serial;
...@@ -223,6 +229,11 @@ static void edge_set_termios(struct tty_struct *tty, ...@@ -223,6 +229,11 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios); struct usb_serial_port *port, struct ktermios *old_termios);
static void edge_send(struct usb_serial_port *port, struct tty_struct *tty); static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
static int do_download_mode(struct edgeport_serial *serial,
const struct firmware *fw);
static int do_boot_mode(struct edgeport_serial *serial,
const struct firmware *fw);
/* sysfs attributes */ /* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port); static int edge_create_sysfs_attrs(struct usb_serial_port *port);
static int edge_remove_sysfs_attrs(struct usb_serial_port *port); static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
...@@ -324,7 +335,8 @@ static int read_download_mem(struct usb_device *dev, int start_address, ...@@ -324,7 +335,8 @@ static int read_download_mem(struct usb_device *dev, int start_address,
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
/* Read in blocks of 64 bytes /*
* Read in blocks of 64 bytes
* (TI firmware can't handle more than 64 byte reads) * (TI firmware can't handle more than 64 byte reads)
*/ */
while (length) { while (length) {
...@@ -430,7 +442,6 @@ static int write_boot_mem(struct edgeport_serial *serial, ...@@ -430,7 +442,6 @@ static int write_boot_mem(struct edgeport_serial *serial,
return status; return status;
} }
/* Write edgeport I2C memory to TI chip */ /* Write edgeport I2C memory to TI chip */
static int write_i2c_mem(struct edgeport_serial *serial, static int write_i2c_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 address_type, __u8 *buffer) int start_address, int length, __u8 address_type, __u8 *buffer)
...@@ -472,8 +483,10 @@ static int write_i2c_mem(struct edgeport_serial *serial, ...@@ -472,8 +483,10 @@ static int write_i2c_mem(struct edgeport_serial *serial,
start_address += write_length; start_address += write_length;
buffer += write_length; buffer += write_length;
/* We should be aligned now -- can write /*
max page size bytes at a time */ * We should be aligned now -- can write max page size bytes at a
* time.
*/
while (length) { while (length) {
if (length > EPROM_PAGE_SIZE) if (length > EPROM_PAGE_SIZE)
write_length = EPROM_PAGE_SIZE; write_length = EPROM_PAGE_SIZE;
...@@ -506,7 +519,8 @@ static int write_i2c_mem(struct edgeport_serial *serial, ...@@ -506,7 +519,8 @@ static int write_i2c_mem(struct edgeport_serial *serial,
return status; return status;
} }
/* Examine the UMP DMA registers and LSR /*
* Examine the UMP DMA registers and LSR
* *
* Check the MSBit of the X and Y DMA byte count registers. * Check the MSBit of the X and Y DMA byte count registers.
* A zero in this bit indicates that the TX DMA buffers are empty * A zero in this bit indicates that the TX DMA buffers are empty
...@@ -523,9 +537,11 @@ static int tx_active(struct edgeport_port *port) ...@@ -523,9 +537,11 @@ static int tx_active(struct edgeport_port *port)
if (!oedb) if (!oedb)
return -ENOMEM; return -ENOMEM;
lsr = kmalloc(1, GFP_KERNEL); /* Sigh, that's right, just one byte, /*
as not all platforms can do DMA * Sigh, that's right, just one byte, as not all platforms can
from stack */ * do DMA from stack
*/
lsr = kmalloc(1, GFP_KERNEL);
if (!lsr) { if (!lsr) {
kfree(oedb); kfree(oedb);
return -ENOMEM; return -ENOMEM;
...@@ -615,8 +631,6 @@ static int write_rom(struct edgeport_serial *serial, int start_address, ...@@ -615,8 +631,6 @@ static int write_rom(struct edgeport_serial *serial, int start_address,
return -EINVAL; return -EINVAL;
} }
/* Read a descriptor header from I2C based on type */ /* Read a descriptor header from I2C based on type */
static int get_descriptor_addr(struct edgeport_serial *serial, static int get_descriptor_addr(struct edgeport_serial *serial,
int desc_type, struct ti_i2c_desc *rom_desc) int desc_type, struct ti_i2c_desc *rom_desc)
...@@ -785,8 +799,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) ...@@ -785,8 +799,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
} }
/* Build firmware header used for firmware update */ /* Build firmware header used for firmware update */
static int build_i2c_fw_hdr(u8 *header, struct device *dev, static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
const struct firmware *fw)
{ {
__u8 *buffer; __u8 *buffer;
int buffer_size; int buffer_size;
...@@ -797,7 +810,8 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev, ...@@ -797,7 +810,8 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
struct ti_i2c_firmware_rec *firmware_rec; struct ti_i2c_firmware_rec *firmware_rec;
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data; struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
/* In order to update the I2C firmware we must change the type 2 record /*
* In order to update the I2C firmware we must change the type 2 record
* to type 0xF2. This will force the UMP to come up in Boot Mode. * to type 0xF2. This will force the UMP to come up in Boot Mode.
* Then while in boot mode, the driver will download the latest * Then while in boot mode, the driver will download the latest
* firmware (padded to 15.5k) into the UMP ram. And finally when the * firmware (padded to 15.5k) into the UMP ram. And finally when the
...@@ -806,8 +820,10 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev, ...@@ -806,8 +820,10 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
* update the record type from 0xf2 to 0x02. * update the record type from 0xf2 to 0x02.
*/ */
/* Allocate a 15.5k buffer + 2 bytes for version number /*
* (Firmware Record) */ * Allocate a 15.5k buffer + 2 bytes for version number (Firmware
* Record)
*/
buffer_size = (((1024 * 16) - 512 ) + buffer_size = (((1024 * 16) - 512 ) +
sizeof(struct ti_i2c_firmware_rec)); sizeof(struct ti_i2c_firmware_rec));
...@@ -815,7 +831,7 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev, ...@@ -815,7 +831,7 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
// Set entire image of 0xffs /* Set entire image of 0xffs */
memset(buffer, 0xff, buffer_size); memset(buffer, 0xff, buffer_size);
/* Copy version number into firmware record */ /* Copy version number into firmware record */
...@@ -981,32 +997,41 @@ static int check_fw_sanity(struct edgeport_serial *serial, ...@@ -981,32 +997,41 @@ static int check_fw_sanity(struct edgeport_serial *serial,
return 0; return 0;
} }
/** /*
* DownloadTIFirmware - Download run-time operating firmware to the TI5052 * DownloadTIFirmware - Download run-time operating firmware to the TI5052
* *
* This routine downloads the main operating code into the TI5052, using the * This routine downloads the main operating code into the TI5052, using the
* boot code already burned into E2PROM or ROM. * boot code already burned into E2PROM or ROM.
*/ */
static int download_fw(struct edgeport_serial *serial, static int download_fw(struct edgeport_serial *serial)
const struct firmware *fw)
{ {
struct device *dev = &serial->serial->dev->dev; struct device *dev = &serial->serial->interface->dev;
int status = 0; int status = 0;
int start_address;
struct edge_ti_manuf_descriptor *ti_manuf_desc;
struct usb_interface_descriptor *interface; struct usb_interface_descriptor *interface;
int download_cur_ver; const struct firmware *fw;
int download_new_ver; const char *fw_name = "edgeport/down3.bin";
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data; struct edgeport_fw_hdr *fw_hdr;
if (check_fw_sanity(serial, fw)) status = request_firmware(&fw, fw_name, dev);
return -EINVAL; if (status) {
dev_err(dev, "Failed to load image \"%s\" err %d\n",
fw_name, status);
return status;
}
if (check_fw_sanity(serial, fw)) {
status = -EINVAL;
goto out;
}
fw_hdr = (struct edgeport_fw_hdr *)fw->data;
/* If on-board version is newer, "fw_version" will be updated below. */ /* If on-board version is newer, "fw_version" will be updated later. */
serial->fw_version = (fw_hdr->major_version << 8) + serial->fw_version = (fw_hdr->major_version << 8) +
fw_hdr->minor_version; fw_hdr->minor_version;
/* This routine is entered by both the BOOT mode and the Download mode /*
* This routine is entered by both the BOOT mode and the Download mode
* We can determine which code is running by the reading the config * We can determine which code is running by the reading the config
* descriptor and if we have only one bulk pipe it is in boot mode * descriptor and if we have only one bulk pipe it is in boot mode
*/ */
...@@ -1017,12 +1042,13 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1017,12 +1042,13 @@ static int download_fw(struct edgeport_serial *serial,
status = choose_config(serial->serial->dev); status = choose_config(serial->serial->dev);
if (status) if (status)
return status; goto out;
interface = &serial->serial->interface->cur_altsetting->desc; interface = &serial->serial->interface->cur_altsetting->desc;
if (!interface) { if (!interface) {
dev_err(dev, "%s - no interface set, error!\n", __func__); dev_err(dev, "%s - no interface set, error!\n", __func__);
return -ENODEV; status = -ENODEV;
goto out;
} }
/* /*
...@@ -1030,16 +1056,30 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1030,16 +1056,30 @@ static int download_fw(struct edgeport_serial *serial,
* if we have more than one endpoint we are definitely in download * if we have more than one endpoint we are definitely in download
* mode * mode
*/ */
if (interface->bNumEndpoints > 1) if (interface->bNumEndpoints > 1) {
serial->product_info.TiMode = TI_MODE_DOWNLOAD; serial->product_info.TiMode = TI_MODE_DOWNLOAD;
else status = do_download_mode(serial, fw);
} else {
/* Otherwise we will remain in configuring mode */ /* Otherwise we will remain in configuring mode */
serial->product_info.TiMode = TI_MODE_CONFIGURING; serial->product_info.TiMode = TI_MODE_CONFIGURING;
status = do_boot_mode(serial, fw);
}
/********************************************************************/ out:
/* Download Mode */ release_firmware(fw);
/********************************************************************/ return status;
if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { }
static int do_download_mode(struct edgeport_serial *serial,
const struct firmware *fw)
{
struct device *dev = &serial->serial->interface->dev;
int status = 0;
int start_address;
struct edge_ti_manuf_descriptor *ti_manuf_desc;
int download_cur_ver;
int download_new_ver;
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
struct ti_i2c_desc *rom_desc; struct ti_i2c_desc *rom_desc;
dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__); dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
...@@ -1050,7 +1090,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1050,7 +1090,8 @@ static int download_fw(struct edgeport_serial *serial,
return status; return status;
} }
/* Validate Hardware version number /*
* Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport * Read Manufacturing Descriptor from TI Based Edgeport
*/ */
ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL); ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
...@@ -1084,7 +1125,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1084,7 +1125,8 @@ static int download_fw(struct edgeport_serial *serial,
struct ti_i2c_firmware_rec *firmware_version; struct ti_i2c_firmware_rec *firmware_version;
u8 *record; u8 *record;
dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__); dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n",
__func__);
firmware_version = kmalloc(sizeof(*firmware_version), firmware_version = kmalloc(sizeof(*firmware_version),
GFP_KERNEL); GFP_KERNEL);
...@@ -1094,7 +1136,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1094,7 +1136,8 @@ static int download_fw(struct edgeport_serial *serial,
return -ENOMEM; return -ENOMEM;
} }
/* Validate version number /*
* Validate version number
* Read the descriptor data * Read the descriptor data
*/ */
status = read_rom(serial, start_address + status = read_rom(serial, start_address +
...@@ -1108,8 +1151,10 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1108,8 +1151,10 @@ static int download_fw(struct edgeport_serial *serial,
return status; return status;
} }
/* Check version number of download with current /*
version in I2c */ * Check version number of download with current
* version in I2c
*/
download_cur_ver = (firmware_version->Ver_Major << 8) + download_cur_ver = (firmware_version->Ver_Major << 8) +
(firmware_version->Ver_Minor); (firmware_version->Ver_Minor);
download_new_ver = (fw_hdr->major_version << 8) + download_new_ver = (fw_hdr->major_version << 8) +
...@@ -1120,8 +1165,10 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1120,8 +1165,10 @@ static int download_fw(struct edgeport_serial *serial,
firmware_version->Ver_Minor, firmware_version->Ver_Minor,
fw_hdr->major_version, fw_hdr->minor_version); fw_hdr->major_version, fw_hdr->minor_version);
/* Check if we have an old version in the I2C and /*
update if necessary */ * Check if we have an old version in the I2C and
* update if necessary
*/
if (download_cur_ver < download_new_ver) { if (download_cur_ver < download_new_ver) {
dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n", dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
__func__, __func__,
...@@ -1137,7 +1184,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1137,7 +1184,8 @@ static int download_fw(struct edgeport_serial *serial,
kfree(ti_manuf_desc); kfree(ti_manuf_desc);
return -ENOMEM; return -ENOMEM;
} }
/* In order to update the I2C firmware we must /*
* In order to update the I2C firmware we must
* change the type 2 record to type 0xF2. This * change the type 2 record to type 0xF2. This
* will force the UMP to come up in Boot Mode. * will force the UMP to come up in Boot Mode.
* Then while in boot mode, the driver will * Then while in boot mode, the driver will
...@@ -1151,8 +1199,10 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1151,8 +1199,10 @@ static int download_fw(struct edgeport_serial *serial,
*/ */
*record = I2C_DESC_TYPE_FIRMWARE_BLANK; *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
/* Change the I2C Firmware record type to /*
0xf2 to trigger an update */ * Change the I2C Firmware record type to
* 0xf2 to trigger an update
*/
status = write_rom(serial, start_address, status = write_rom(serial, start_address,
sizeof(*record), record); sizeof(*record), record);
if (status) { if (status) {
...@@ -1163,7 +1213,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1163,7 +1213,8 @@ static int download_fw(struct edgeport_serial *serial,
return status; return status;
} }
/* verify the write -- must do this in order /*
* verify the write -- must do this in order
* for write to complete before we do the * for write to complete before we do the
* hardware reset * hardware reset
*/ */
...@@ -1180,7 +1231,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1180,7 +1231,8 @@ static int download_fw(struct edgeport_serial *serial,
} }
if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) { if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
dev_err(dev, "%s - error resetting device\n", __func__); dev_err(dev, "%s - error resetting device\n",
__func__);
kfree(record); kfree(record);
kfree(firmware_version); kfree(firmware_version);
kfree(rom_desc); kfree(rom_desc);
...@@ -1196,7 +1248,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1196,7 +1248,8 @@ static int download_fw(struct edgeport_serial *serial,
0, 0, NULL, 0, 0, 0, NULL, 0,
TI_VSEND_TIMEOUT_DEFAULT); TI_VSEND_TIMEOUT_DEFAULT);
dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status); dev_dbg(dev, "%s - HARDWARE RESET return %d\n",
__func__, status);
/* return an error on purpose. */ /* return an error on purpose. */
kfree(record); kfree(record);
...@@ -1204,14 +1257,16 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1204,14 +1257,16 @@ static int download_fw(struct edgeport_serial *serial,
kfree(rom_desc); kfree(rom_desc);
kfree(ti_manuf_desc); kfree(ti_manuf_desc);
return -ENODEV; return -ENODEV;
} else { }
/* Same or newer fw version is already loaded */ /* Same or newer fw version is already loaded */
serial->fw_version = download_cur_ver; serial->fw_version = download_cur_ver;
}
kfree(firmware_version); kfree(firmware_version);
} }
/* Search for type 0xF2 record (firmware blank record) */ /* Search for type 0xF2 record (firmware blank record) */
else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { else {
start_address = get_descriptor_addr(serial,
I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc);
if (start_address != 0) {
#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \ #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \
sizeof(struct ti_i2c_firmware_rec)) sizeof(struct ti_i2c_firmware_rec))
__u8 *header; __u8 *header;
...@@ -1232,7 +1287,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1232,7 +1287,8 @@ static int download_fw(struct edgeport_serial *serial,
return -ENOMEM; return -ENOMEM;
} }
dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__); dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n",
__func__);
/* /*
* In order to update the I2C firmware we must change * In order to update the I2C firmware we must change
...@@ -1245,7 +1301,7 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1245,7 +1301,7 @@ static int download_fw(struct edgeport_serial *serial,
* UMP Ram to I2C and the firmware will update the * UMP Ram to I2C and the firmware will update the
* record type from 0xf2 to 0x02. * record type from 0xf2 to 0x02.
*/ */
status = build_i2c_fw_hdr(header, dev, fw); status = build_i2c_fw_hdr(header, fw);
if (status) { if (status) {
kfree(vheader); kfree(vheader);
kfree(header); kfree(header);
...@@ -1254,8 +1310,10 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1254,8 +1310,10 @@ static int download_fw(struct edgeport_serial *serial,
return -EINVAL; return -EINVAL;
} }
/* Update I2C with type 0xf2 record with correct /*
size and checksum */ * Update I2C with type 0xf2 record with correct
* size and checksum
*/
status = write_rom(serial, status = write_rom(serial,
start_address, start_address,
HEADER_SIZE, HEADER_SIZE,
...@@ -1268,13 +1326,16 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1268,13 +1326,16 @@ static int download_fw(struct edgeport_serial *serial,
return -EINVAL; return -EINVAL;
} }
/* verify the write -- must do this in order for /*
write to complete before we do the hardware reset */ * verify the write -- must do this in order for
* write to complete before we do the hardware reset
*/
status = read_rom(serial, start_address, status = read_rom(serial, start_address,
HEADER_SIZE, vheader); HEADER_SIZE, vheader);
if (status) { if (status) {
dev_dbg(dev, "%s - can't read header back\n", __func__); dev_dbg(dev, "%s - can't read header back\n",
__func__);
kfree(vheader); kfree(vheader);
kfree(header); kfree(header);
kfree(rom_desc); kfree(rom_desc);
...@@ -1282,7 +1343,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1282,7 +1343,8 @@ static int download_fw(struct edgeport_serial *serial,
return status; return status;
} }
if (memcmp(vheader, header, HEADER_SIZE)) { if (memcmp(vheader, header, HEADER_SIZE)) {
dev_dbg(dev, "%s - write download record failed\n", __func__); dev_dbg(dev, "%s - write download record failed\n",
__func__);
kfree(vheader); kfree(vheader);
kfree(header); kfree(header);
kfree(rom_desc); kfree(rom_desc);
...@@ -1301,7 +1363,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1301,7 +1363,8 @@ static int download_fw(struct edgeport_serial *serial,
0, 0, NULL, 0, 0, 0, NULL, 0,
TI_VSEND_TIMEOUT_FW_DOWNLOAD); TI_VSEND_TIMEOUT_FW_DOWNLOAD);
dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status); dev_dbg(dev, "%s - Update complete 0x%x\n", __func__,
status);
if (status) { if (status) {
dev_err(dev, dev_err(dev,
"%s - UMPC_COPY_DNLD_TO_I2C failed\n", "%s - UMPC_COPY_DNLD_TO_I2C failed\n",
...@@ -1311,16 +1374,22 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1311,16 +1374,22 @@ static int download_fw(struct edgeport_serial *serial,
return status; return status;
} }
} }
}
// The device is running the download code /* The device is running the download code */
kfree(rom_desc); kfree(rom_desc);
kfree(ti_manuf_desc); kfree(ti_manuf_desc);
return 0; return 0;
} }
static int do_boot_mode(struct edgeport_serial *serial,
const struct firmware *fw)
{
struct device *dev = &serial->serial->interface->dev;
int status = 0;
struct edge_ti_manuf_descriptor *ti_manuf_desc;
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
/********************************************************************/
/* Boot Mode */
/********************************************************************/
dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__); dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
/* Configure the TI device so we can use the BULK pipes for download */ /* Configure the TI device so we can use the BULK pipes for download */
...@@ -1336,8 +1405,10 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1336,8 +1405,10 @@ static int download_fw(struct edgeport_serial *serial,
goto stayinbootmode; goto stayinbootmode;
} }
/* We have an ION device (I2c Must be programmed) /*
Determine I2C image type */ * We have an ION device (I2c Must be programmed)
* Determine I2C image type
*/
if (i2c_type_bootmode(serial)) if (i2c_type_bootmode(serial))
goto stayinbootmode; goto stayinbootmode;
...@@ -1349,7 +1420,8 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1349,7 +1420,8 @@ static int download_fw(struct edgeport_serial *serial,
__u8 *buffer; __u8 *buffer;
int buffer_size; int buffer_size;
/* Validate Hardware version number /*
* Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport * Read Manufacturing Descriptor from TI Based Edgeport
*/ */
ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL); ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
...@@ -1439,7 +1511,6 @@ static int download_fw(struct edgeport_serial *serial, ...@@ -1439,7 +1511,6 @@ static int download_fw(struct edgeport_serial *serial,
return 0; return 0;
} }
static int ti_do_config(struct edgeport_port *port, int feature, int on) static int ti_do_config(struct edgeport_port *port, int feature, int on)
{ {
int port_number = port->port->port_number; int port_number = port->port->port_number;
...@@ -1450,7 +1521,6 @@ static int ti_do_config(struct edgeport_port *port, int feature, int on) ...@@ -1450,7 +1521,6 @@ static int ti_do_config(struct edgeport_port *port, int feature, int on)
on, NULL, 0); on, NULL, 0);
} }
static int restore_mcr(struct edgeport_port *port, __u8 mcr) static int restore_mcr(struct edgeport_port *port, __u8 mcr)
{ {
int status = 0; int status = 0;
...@@ -1556,7 +1626,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, ...@@ -1556,7 +1626,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
icount->frame++; icount->frame++;
} }
static void edge_interrupt_callback(struct urb *urb) static void edge_interrupt_callback(struct urb *urb)
{ {
struct edgeport_serial *edge_serial = urb->context; struct edgeport_serial *edge_serial = urb->context;
...@@ -1616,8 +1685,9 @@ static void edge_interrupt_callback(struct urb *urb) ...@@ -1616,8 +1685,9 @@ static void edge_interrupt_callback(struct urb *urb)
case TIUMP_INTERRUPT_CODE_LSR: case TIUMP_INTERRUPT_CODE_LSR:
lsr = map_line_status(data[1]); lsr = map_line_status(data[1]);
if (lsr & UMP_UART_LSR_DATA_MASK) { if (lsr & UMP_UART_LSR_DATA_MASK) {
/* Save the LSR event for bulk read /*
completion routine */ * Save the LSR event for bulk read completion routine
*/
dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n", dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n",
__func__, port_number, lsr); __func__, port_number, lsr);
edge_port->lsr_event = 1; edge_port->lsr_event = 1;
...@@ -1925,8 +1995,10 @@ static void edge_close(struct usb_serial_port *port) ...@@ -1925,8 +1995,10 @@ static void edge_close(struct usb_serial_port *port)
if (edge_serial == NULL || edge_port == NULL) if (edge_serial == NULL || edge_port == NULL)
return; return;
/* The bulkreadcompletion routine will check /*
* this flag and dump add read data */ * The bulkreadcompletion routine will check
* this flag and dump add read data
*/
edge_port->close_pending = 1; edge_port->close_pending = 1;
usb_kill_urb(port->read_urb); usb_kill_urb(port->read_urb);
...@@ -2016,8 +2088,10 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty) ...@@ -2016,8 +2088,10 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
} else } else
edge_port->port->icount.tx += count; edge_port->port->icount.tx += count;
/* wakeup any process waiting for writes to complete */ /*
/* there is now more room in the buffer for new writes */ * wakeup any process waiting for writes to complete
* there is now more room in the buffer for new writes
*/
if (tty) if (tty)
tty_wakeup(tty); tty_wakeup(tty);
} }
...@@ -2089,8 +2163,10 @@ static void edge_throttle(struct tty_struct *tty) ...@@ -2089,8 +2163,10 @@ static void edge_throttle(struct tty_struct *tty)
} }
} }
/* if we are implementing RTS/CTS, stop reads */ /*
/* and the Edgeport will clear the RTS line */ * if we are implementing RTS/CTS, stop reads
* and the Edgeport will clear the RTS line
*/
if (C_CRTSCTS(tty)) if (C_CRTSCTS(tty))
stop_read(edge_port); stop_read(edge_port);
...@@ -2113,8 +2189,10 @@ static void edge_unthrottle(struct tty_struct *tty) ...@@ -2113,8 +2189,10 @@ static void edge_unthrottle(struct tty_struct *tty)
dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status); dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
} }
} }
/* if we are implementing RTS/CTS, restart reads */ /*
/* are the Edgeport will assert the RTS line */ * if we are implementing RTS/CTS, restart reads
* are the Edgeport will assert the RTS line
*/
if (C_CRTSCTS(tty)) { if (C_CRTSCTS(tty)) {
status = restart_read(edge_port); status = restart_read(edge_port);
if (status) if (status)
...@@ -2236,8 +2314,10 @@ static void change_port_settings(struct tty_struct *tty, ...@@ -2236,8 +2314,10 @@ static void change_port_settings(struct tty_struct *tty,
restart_read(edge_port); restart_read(edge_port);
} }
/* if we are implementing XON/XOFF, set the start and stop /*
character in the device */ * if we are implementing XON/XOFF, set the start and stop
* character in the device
*/
config->cXon = START_CHAR(tty); config->cXon = START_CHAR(tty);
config->cXoff = STOP_CHAR(tty); config->cXoff = STOP_CHAR(tty);
...@@ -2467,9 +2547,6 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2467,9 +2547,6 @@ static int edge_startup(struct usb_serial *serial)
{ {
struct edgeport_serial *edge_serial; struct edgeport_serial *edge_serial;
int status; int status;
const struct firmware *fw;
const char *fw_name = "edgeport/down3.bin";
struct device *dev = &serial->interface->dev;
u16 product_id; u16 product_id;
/* create our private serial structure */ /* create our private serial structure */
...@@ -2481,16 +2558,7 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2481,16 +2558,7 @@ static int edge_startup(struct usb_serial *serial)
edge_serial->serial = serial; edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial); usb_set_serial_data(serial, edge_serial);
status = request_firmware(&fw, fw_name, dev); status = download_fw(edge_serial);
if (status) {
dev_err(dev, "Failed to load image \"%s\" err %d\n",
fw_name, status);
kfree(edge_serial);
return status;
}
status = download_fw(edge_serial, fw);
release_firmware(fw);
if (status) { if (status) {
kfree(edge_serial); kfree(edge_serial);
return status; return status;
......
...@@ -48,7 +48,6 @@ static int option_probe(struct usb_serial *serial, ...@@ -48,7 +48,6 @@ static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id); const struct usb_device_id *id);
static int option_attach(struct usb_serial *serial); static int option_attach(struct usb_serial *serial);
static void option_release(struct usb_serial *serial); static void option_release(struct usb_serial *serial);
static int option_send_setup(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb); static void option_instat_callback(struct urb *urb);
/* Vendor and product IDs */ /* Vendor and product IDs */
...@@ -234,8 +233,6 @@ static void option_instat_callback(struct urb *urb); ...@@ -234,8 +233,6 @@ static void option_instat_callback(struct urb *urb);
#define QUALCOMM_VENDOR_ID 0x05C6 #define QUALCOMM_VENDOR_ID 0x05C6
#define SIERRA_VENDOR_ID 0x1199
#define CMOTECH_VENDOR_ID 0x16d8 #define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001 #define CMOTECH_PRODUCT_6001 0x6001
#define CMOTECH_PRODUCT_CMU_300 0x6002 #define CMOTECH_PRODUCT_CMU_300 0x6002
...@@ -611,11 +608,6 @@ static const struct option_blacklist_info telit_le920_blacklist = { ...@@ -611,11 +608,6 @@ static const struct option_blacklist_info telit_le920_blacklist = {
.reserved = BIT(1) | BIT(5), .reserved = BIT(1) | BIT(5),
}; };
static const struct option_blacklist_info sierra_mc73xx_blacklist = {
.sendsetup = BIT(0) | BIT(2),
.reserved = BIT(8) | BIT(10) | BIT(11),
};
static const struct usb_device_id option_ids[] = { static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
...@@ -1113,10 +1105,6 @@ static const struct usb_device_id option_ids[] = { ...@@ -1113,10 +1105,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
.driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff),
.driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
...@@ -1835,10 +1823,6 @@ static struct usb_serial_driver * const serial_drivers[] = { ...@@ -1835,10 +1823,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
&option_1port_device, NULL &option_1port_device, NULL
}; };
struct option_private {
u8 bInterfaceNumber;
};
module_usb_serial_driver(serial_drivers, option_ids); module_usb_serial_driver(serial_drivers, option_ids);
static int option_probe(struct usb_serial *serial, static int option_probe(struct usb_serial *serial,
...@@ -1882,29 +1866,19 @@ static int option_attach(struct usb_serial *serial) ...@@ -1882,29 +1866,19 @@ static int option_attach(struct usb_serial *serial)
struct usb_interface_descriptor *iface_desc; struct usb_interface_descriptor *iface_desc;
const struct option_blacklist_info *blacklist; const struct option_blacklist_info *blacklist;
struct usb_wwan_intf_private *data; struct usb_wwan_intf_private *data;
struct option_private *priv;
data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
kfree(data);
return -ENOMEM;
}
/* Retrieve blacklist info stored at probe. */ /* Retrieve blacklist info stored at probe. */
blacklist = usb_get_serial_data(serial); blacklist = usb_get_serial_data(serial);
iface_desc = &serial->interface->cur_altsetting->desc; iface_desc = &serial->interface->cur_altsetting->desc;
priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
data->private = priv;
if (!blacklist || !test_bit(iface_desc->bInterfaceNumber, if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
&blacklist->sendsetup)) { &blacklist->sendsetup)) {
data->send_setup = option_send_setup; data->use_send_setup = 1;
} }
spin_lock_init(&data->susp_lock); spin_lock_init(&data->susp_lock);
...@@ -1916,9 +1890,7 @@ static int option_attach(struct usb_serial *serial) ...@@ -1916,9 +1890,7 @@ static int option_attach(struct usb_serial *serial)
static void option_release(struct usb_serial *serial) static void option_release(struct usb_serial *serial)
{ {
struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
struct option_private *priv = intfdata->private;
kfree(priv);
kfree(intfdata); kfree(intfdata);
} }
...@@ -1977,40 +1949,6 @@ static void option_instat_callback(struct urb *urb) ...@@ -1977,40 +1949,6 @@ static void option_instat_callback(struct urb *urb)
} }
} }
/** 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 usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
struct option_private *priv = intfdata->private;
struct usb_wwan_port_private *portdata;
int val = 0;
int res;
portdata = usb_get_serial_port_data(port);
if (portdata->dtr_state)
val |= 0x01;
if (portdata->rts_state)
val |= 0x02;
res = usb_autopm_get_interface(serial->interface);
if (res)
return res;
res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0x22, 0x21, val, priv->bInterfaceNumber, NULL,
0, USB_CTRL_SET_TIMEOUT);
usb_autopm_put_interface(serial->interface);
return res;
}
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -143,9 +143,11 @@ static const struct usb_device_id id_table[] = { ...@@ -143,9 +143,11 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */ {DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */
{DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */ {DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */
{DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */ {DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */
{DEVICE_SWI(0x1199, 0x68c0)}, /* Sierra Wireless MC7304/MC7354 */
{DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */ {DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */
{DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */ {DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */
{DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */
{DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */ {DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */
{DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */
...@@ -175,6 +177,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ...@@ -175,6 +177,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
__u8 nintf; __u8 nintf;
__u8 ifnum; __u8 ifnum;
int altsetting = -1; int altsetting = -1;
bool sendsetup = false;
nintf = serial->dev->actconfig->desc.bNumInterfaces; nintf = serial->dev->actconfig->desc.bNumInterfaces;
dev_dbg(dev, "Num Interfaces = %d\n", nintf); dev_dbg(dev, "Num Interfaces = %d\n", nintf);
...@@ -286,6 +289,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ...@@ -286,6 +289,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
break; break;
case 3: case 3:
dev_dbg(dev, "Modem port found\n"); dev_dbg(dev, "Modem port found\n");
sendsetup = true;
break; break;
default: default:
/* don't claim any unsupported interface */ /* don't claim any unsupported interface */
...@@ -337,17 +341,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ...@@ -337,17 +341,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
} }
} }
if (!retval)
usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);
return retval; return retval;
} }
static int qc_attach(struct usb_serial *serial) static int qc_attach(struct usb_serial *serial)
{ {
struct usb_wwan_intf_private *data; struct usb_wwan_intf_private *data;
bool sendsetup;
data = kzalloc(sizeof(*data), GFP_KERNEL); data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
if (sendsetup)
data->use_send_setup = 1;
spin_lock_init(&data->susp_lock); spin_lock_init(&data->susp_lock);
usb_set_serial_data(serial, data); usb_set_serial_data(serial, data);
...@@ -374,6 +386,7 @@ static struct usb_serial_driver qcdevice = { ...@@ -374,6 +386,7 @@ static struct usb_serial_driver qcdevice = {
.probe = qcprobe, .probe = qcprobe,
.open = usb_wwan_open, .open = usb_wwan_open,
.close = usb_wwan_close, .close = usb_wwan_close,
.dtr_rts = usb_wwan_dtr_rts,
.write = usb_wwan_write, .write = usb_wwan_write,
.write_room = usb_wwan_write_room, .write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer, .chars_in_buffer = usb_wwan_chars_in_buffer,
......
...@@ -34,9 +34,9 @@ extern int usb_wwan_resume(struct usb_serial *serial); ...@@ -34,9 +34,9 @@ extern int usb_wwan_resume(struct usb_serial *serial);
struct usb_wwan_intf_private { struct usb_wwan_intf_private {
spinlock_t susp_lock; spinlock_t susp_lock;
unsigned int suspended:1; unsigned int suspended:1;
unsigned int use_send_setup:1;
int in_flight; int in_flight;
unsigned int open_ports; unsigned int open_ports;
int (*send_setup) (struct usb_serial_port *port);
void *private; void *private;
}; };
......
...@@ -36,6 +36,40 @@ ...@@ -36,6 +36,40 @@
#include <linux/serial.h> #include <linux/serial.h>
#include "usb-wwan.h" #include "usb-wwan.h"
/*
* Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
* in CDC ACM.
*/
static int usb_wwan_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct usb_wwan_port_private *portdata;
int val = 0;
int ifnum;
int res;
portdata = usb_get_serial_port_data(port);
if (portdata->dtr_state)
val |= 0x01;
if (portdata->rts_state)
val |= 0x02;
ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
res = usb_autopm_get_interface(serial->interface);
if (res)
return res;
res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0x22, 0x21, val, ifnum, NULL, 0,
USB_CTRL_SET_TIMEOUT);
usb_autopm_put_interface(port->serial->interface);
return res;
}
void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
{ {
struct usb_wwan_port_private *portdata; struct usb_wwan_port_private *portdata;
...@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) ...@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
intfdata = usb_get_serial_data(port->serial); intfdata = usb_get_serial_data(port->serial);
if (!intfdata->send_setup) if (!intfdata->use_send_setup)
return; return;
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
...@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) ...@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
portdata->rts_state = on; portdata->rts_state = on;
portdata->dtr_state = on; portdata->dtr_state = on;
intfdata->send_setup(port); usb_wwan_send_setup(port);
} }
EXPORT_SYMBOL(usb_wwan_dtr_rts); EXPORT_SYMBOL(usb_wwan_dtr_rts);
...@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty, ...@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
portdata = usb_get_serial_port_data(port); portdata = usb_get_serial_port_data(port);
intfdata = usb_get_serial_data(port->serial); intfdata = usb_get_serial_data(port->serial);
if (!intfdata->send_setup) if (!intfdata->use_send_setup)
return -EINVAL; return -EINVAL;
/* FIXME: what locks portdata fields ? */ /* FIXME: what locks portdata fields ? */
...@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty, ...@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
portdata->rts_state = 0; portdata->rts_state = 0;
if (clear & TIOCM_DTR) if (clear & TIOCM_DTR)
portdata->dtr_state = 0; portdata->dtr_state = 0;
return intfdata->send_setup(port); return usb_wwan_send_setup(port);
} }
EXPORT_SYMBOL(usb_wwan_tiocmset); EXPORT_SYMBOL(usb_wwan_tiocmset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment