aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/serial/option.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index b4fe9ffd6dd6..85e5fc08bba6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -346,6 +346,19 @@ static int option_resume(struct usb_serial *serial);
346#define HAIER_VENDOR_ID 0x201e 346#define HAIER_VENDOR_ID 0x201e
347#define HAIER_PRODUCT_CE100 0x2009 347#define HAIER_PRODUCT_CE100 0x2009
348 348
349/* some devices interfaces need special handling due to a number of reasons */
350enum option_blacklist_reason {
351 OPTION_BLACKLIST_NONE = 0,
352 OPTION_BLACKLIST_SENDSETUP = 1,
353 OPTION_BLACKLIST_RESERVED_IF = 2
354};
355
356struct option_blacklist_info {
357 const u32 infolen; /* number of interface numbers on blacklist */
358 const u8 *ifaceinfo; /* pointer to the array holding the numbers */
359 enum option_blacklist_reason reason;
360};
361
349static const struct usb_device_id option_ids[] = { 362static const struct usb_device_id option_ids[] = {
350 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, 363 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
351 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, 364 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -711,6 +724,7 @@ struct option_intf_private {
711 spinlock_t susp_lock; 724 spinlock_t susp_lock;
712 unsigned int suspended:1; 725 unsigned int suspended:1;
713 int in_flight; 726 int in_flight;
727 struct option_blacklist_info *blacklist_info;
714}; 728};
715 729
716struct option_port_private { 730struct option_port_private {
@@ -780,9 +794,27 @@ static int option_probe(struct usb_serial *serial,
780 if (!data) 794 if (!data)
781 return -ENOMEM; 795 return -ENOMEM;
782 spin_lock_init(&data->susp_lock); 796 spin_lock_init(&data->susp_lock);
797 data->blacklist_info = (struct option_blacklist_info*) id->driver_info;
783 return 0; 798 return 0;
784} 799}
785 800
801static enum option_blacklist_reason is_blacklisted(const u8 ifnum,
802 const struct option_blacklist_info *blacklist)
803{
804 const u8 *info;
805 int i;
806
807 if (blacklist) {
808 info = blacklist->ifaceinfo;
809
810 for (i = 0; i < blacklist->infolen; i++) {
811 if (info[i] == ifnum)
812 return blacklist->reason;
813 }
814 }
815 return OPTION_BLACKLIST_NONE;
816}
817
786static void option_set_termios(struct tty_struct *tty, 818static void option_set_termios(struct tty_struct *tty,
787 struct usb_serial_port *port, struct ktermios *old_termios) 819 struct usb_serial_port *port, struct ktermios *old_termios)
788{ 820{
@@ -1213,11 +1245,19 @@ static void option_setup_urbs(struct usb_serial *serial)
1213static int option_send_setup(struct usb_serial_port *port) 1245static int option_send_setup(struct usb_serial_port *port)
1214{ 1246{
1215 struct usb_serial *serial = port->serial; 1247 struct usb_serial *serial = port->serial;
1248 struct option_intf_private *intfdata =
1249 (struct option_intf_private *) serial->private;
1216 struct option_port_private *portdata; 1250 struct option_port_private *portdata;
1217 int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; 1251 int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
1218 int val = 0; 1252 int val = 0;
1219 dbg("%s", __func__); 1253 dbg("%s", __func__);
1220 1254
1255 if (is_blacklisted(ifNum, intfdata->blacklist_info) ==
1256 OPTION_BLACKLIST_SENDSETUP) {
1257 dbg("No send_setup on blacklisted interface #%d\n", ifNum);
1258 return -EIO;
1259 }
1260
1221 portdata = usb_get_serial_port_data(port); 1261 portdata = usb_get_serial_port_data(port);
1222 1262
1223 if (portdata->dtr_state) 1263 if (portdata->dtr_state)