|
@@ -17,30 +17,11 @@
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
|
|
|
|
-#include <linux/module.h>
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/kernel.h>
|
|
-#include <linux/delay.h>
|
|
|
|
-#include <linux/ioport.h>
|
|
|
|
-#include <linux/slab.h>
|
|
|
|
-#include <linux/errno.h>
|
|
|
|
-#include <linux/init.h>
|
|
|
|
-#include <linux/timer.h>
|
|
|
|
-#include <linux/list.h>
|
|
|
|
-#include <linux/interrupt.h>
|
|
|
|
#include <linux/utsname.h>
|
|
#include <linux/utsname.h>
|
|
-#include <linux/wait.h>
|
|
|
|
-#include <linux/proc_fs.h>
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/device.h>
|
|
#include <linux/tty.h>
|
|
#include <linux/tty.h>
|
|
#include <linux/tty_flip.h>
|
|
#include <linux/tty_flip.h>
|
|
-#include <linux/mutex.h>
|
|
|
|
-
|
|
|
|
-#include <asm/byteorder.h>
|
|
|
|
-#include <asm/io.h>
|
|
|
|
-#include <asm/irq.h>
|
|
|
|
-#include <asm/system.h>
|
|
|
|
-#include <asm/unaligned.h>
|
|
|
|
-#include <asm/uaccess.h>
|
|
|
|
|
|
|
|
#include <linux/usb/ch9.h>
|
|
#include <linux/usb/ch9.h>
|
|
#include <linux/usb/cdc.h>
|
|
#include <linux/usb/cdc.h>
|
|
@@ -89,30 +70,29 @@
|
|
#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY
|
|
#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY
|
|
#define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS
|
|
#define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS
|
|
|
|
|
|
-/* select highspeed/fullspeed, hiding highspeed if not configured */
|
|
|
|
-#ifdef CONFIG_USB_GADGET_DUALSPEED
|
|
|
|
-#define GS_SPEED_SELECT(is_hs,hs,fs) ((is_hs) ? (hs) : (fs))
|
|
|
|
-#else
|
|
|
|
-#define GS_SPEED_SELECT(is_hs,hs,fs) (fs)
|
|
|
|
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
|
|
|
|
|
+/* maxpacket and other transfer characteristics vary by speed. */
|
|
|
|
+static inline struct usb_endpoint_descriptor *
|
|
|
|
+choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
|
|
|
|
+ struct usb_endpoint_descriptor *fs)
|
|
|
|
+{
|
|
|
|
+ if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
|
|
|
+ return hs;
|
|
|
|
+ return fs;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
/* debug settings */
|
|
/* debug settings */
|
|
-#ifdef GS_DEBUG
|
|
|
|
|
|
+#ifdef DEBUG
|
|
static int debug = 1;
|
|
static int debug = 1;
|
|
|
|
+#else
|
|
|
|
+#define debug 0
|
|
|
|
+#endif
|
|
|
|
|
|
#define gs_debug(format, arg...) \
|
|
#define gs_debug(format, arg...) \
|
|
do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0)
|
|
do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0)
|
|
#define gs_debug_level(level, format, arg...) \
|
|
#define gs_debug_level(level, format, arg...) \
|
|
do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0)
|
|
do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0)
|
|
|
|
|
|
-#else
|
|
|
|
-
|
|
|
|
-#define gs_debug(format, arg...) \
|
|
|
|
- do { } while(0)
|
|
|
|
-#define gs_debug_level(level, format, arg...) \
|
|
|
|
- do { } while(0)
|
|
|
|
-
|
|
|
|
-#endif /* GS_DEBUG */
|
|
|
|
|
|
|
|
/* Thanks to NetChip Technologies for donating this product ID.
|
|
/* Thanks to NetChip Technologies for donating this product ID.
|
|
*
|
|
*
|
|
@@ -147,10 +127,10 @@ struct gs_req_entry {
|
|
|
|
|
|
/* the port structure holds info for each port, one for each minor number */
|
|
/* the port structure holds info for each port, one for each minor number */
|
|
struct gs_port {
|
|
struct gs_port {
|
|
- struct gs_dev *port_dev; /* pointer to device struct */
|
|
|
|
|
|
+ struct gs_dev *port_dev; /* pointer to device struct */
|
|
struct tty_struct *port_tty; /* pointer to tty struct */
|
|
struct tty_struct *port_tty; /* pointer to tty struct */
|
|
spinlock_t port_lock;
|
|
spinlock_t port_lock;
|
|
- int port_num;
|
|
|
|
|
|
+ int port_num;
|
|
int port_open_count;
|
|
int port_open_count;
|
|
int port_in_use; /* open/close in progress */
|
|
int port_in_use; /* open/close in progress */
|
|
wait_queue_head_t port_write_wait;/* waiting to write */
|
|
wait_queue_head_t port_write_wait;/* waiting to write */
|
|
@@ -188,7 +168,7 @@ static void __exit gs_module_exit(void);
|
|
/* tty driver */
|
|
/* tty driver */
|
|
static int gs_open(struct tty_struct *tty, struct file *file);
|
|
static int gs_open(struct tty_struct *tty, struct file *file);
|
|
static void gs_close(struct tty_struct *tty, struct file *file);
|
|
static void gs_close(struct tty_struct *tty, struct file *file);
|
|
-static int gs_write(struct tty_struct *tty,
|
|
|
|
|
|
+static int gs_write(struct tty_struct *tty,
|
|
const unsigned char *buf, int count);
|
|
const unsigned char *buf, int count);
|
|
static void gs_put_char(struct tty_struct *tty, unsigned char ch);
|
|
static void gs_put_char(struct tty_struct *tty, unsigned char ch);
|
|
static void gs_flush_chars(struct tty_struct *tty);
|
|
static void gs_flush_chars(struct tty_struct *tty);
|
|
@@ -222,7 +202,7 @@ static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req);
|
|
static void gs_disconnect(struct usb_gadget *gadget);
|
|
static void gs_disconnect(struct usb_gadget *gadget);
|
|
static int gs_set_config(struct gs_dev *dev, unsigned config);
|
|
static int gs_set_config(struct gs_dev *dev, unsigned config);
|
|
static void gs_reset_config(struct gs_dev *dev);
|
|
static void gs_reset_config(struct gs_dev *dev);
|
|
-static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
|
|
|
|
|
|
+static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
|
|
u8 type, unsigned int index, int is_otg);
|
|
u8 type, unsigned int index, int is_otg);
|
|
|
|
|
|
static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
|
|
static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
|
|
@@ -415,18 +395,18 @@ static const struct usb_cdc_header_desc gs_header_desc = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
|
|
static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
|
|
- .bLength = sizeof(gs_call_mgmt_descriptor),
|
|
|
|
- .bDescriptorType = USB_DT_CS_INTERFACE,
|
|
|
|
- .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
|
|
|
|
- .bmCapabilities = 0,
|
|
|
|
- .bDataInterface = 1, /* index of data interface */
|
|
|
|
|
|
+ .bLength = sizeof(gs_call_mgmt_descriptor),
|
|
|
|
+ .bDescriptorType = USB_DT_CS_INTERFACE,
|
|
|
|
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
|
|
|
|
+ .bmCapabilities = 0,
|
|
|
|
+ .bDataInterface = 1, /* index of data interface */
|
|
};
|
|
};
|
|
|
|
|
|
static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
|
|
static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
|
|
- .bLength = sizeof(gs_acm_descriptor),
|
|
|
|
- .bDescriptorType = USB_DT_CS_INTERFACE,
|
|
|
|
- .bDescriptorSubType = USB_CDC_ACM_TYPE,
|
|
|
|
- .bmCapabilities = 0,
|
|
|
|
|
|
+ .bLength = sizeof(gs_acm_descriptor),
|
|
|
|
+ .bDescriptorType = USB_DT_CS_INTERFACE,
|
|
|
|
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
|
|
|
|
+ .bmCapabilities = 0,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct usb_cdc_union_desc gs_union_desc = {
|
|
static const struct usb_cdc_union_desc gs_union_desc = {
|
|
@@ -436,7 +416,7 @@ static const struct usb_cdc_union_desc gs_union_desc = {
|
|
.bMasterInterface0 = 0, /* index of control interface */
|
|
.bMasterInterface0 = 0, /* index of control interface */
|
|
.bSlaveInterface0 = 1, /* index of data interface */
|
|
.bSlaveInterface0 = 1, /* index of data interface */
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+
|
|
static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
|
|
static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
|
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
.bDescriptorType = USB_DT_ENDPOINT,
|
|
.bDescriptorType = USB_DT_ENDPOINT,
|
|
@@ -482,7 +462,6 @@ static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-#ifdef CONFIG_USB_GADGET_DUALSPEED
|
|
|
|
static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
|
|
static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
|
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
.bDescriptorType = USB_DT_ENDPOINT,
|
|
.bDescriptorType = USB_DT_ENDPOINT,
|
|
@@ -536,15 +515,13 @@ static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
|
|
|
-
|
|
|
|
|
|
|
|
/* Module */
|
|
/* Module */
|
|
MODULE_DESCRIPTION(GS_LONG_NAME);
|
|
MODULE_DESCRIPTION(GS_LONG_NAME);
|
|
MODULE_AUTHOR("Al Borchers");
|
|
MODULE_AUTHOR("Al Borchers");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
-#ifdef GS_DEBUG
|
|
|
|
|
|
+#ifdef DEBUG
|
|
module_param(debug, int, S_IRUGO|S_IWUSR);
|
|
module_param(debug, int, S_IRUGO|S_IWUSR);
|
|
MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
|
|
MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
|
|
#endif
|
|
#endif
|
|
@@ -915,7 +892,8 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2));
|
|
|
|
|
|
+ gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
|
|
|
|
+ port->port_num, tty, ch, __builtin_return_address(0));
|
|
|
|
|
|
spin_lock_irqsave(&port->port_lock, flags);
|
|
spin_lock_irqsave(&port->port_lock, flags);
|
|
|
|
|
|
@@ -1116,7 +1094,11 @@ static int gs_send(struct gs_dev *dev)
|
|
len = gs_send_packet(dev, req->buf, ep->maxpacket);
|
|
len = gs_send_packet(dev, req->buf, ep->maxpacket);
|
|
|
|
|
|
if (len > 0) {
|
|
if (len > 0) {
|
|
-gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
|
|
|
|
|
|
+ gs_debug_level(3, "gs_send: len=%d, 0x%2.2x "
|
|
|
|
+ "0x%2.2x 0x%2.2x ...\n", len,
|
|
|
|
+ *((unsigned char *)req->buf),
|
|
|
|
+ *((unsigned char *)req->buf+1),
|
|
|
|
+ *((unsigned char *)req->buf+2));
|
|
list_del(&req_entry->re_entry);
|
|
list_del(&req_entry->re_entry);
|
|
req->length = len;
|
|
req->length = len;
|
|
spin_unlock_irqrestore(&dev->dev_lock, flags);
|
|
spin_unlock_irqrestore(&dev->dev_lock, flags);
|
|
@@ -1269,7 +1251,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
|
|
|
|
|
|
switch(req->status) {
|
|
switch(req->status) {
|
|
case 0:
|
|
case 0:
|
|
- /* normal completion */
|
|
|
|
|
|
+ /* normal completion */
|
|
gs_recv_packet(dev, req->buf, req->actual);
|
|
gs_recv_packet(dev, req->buf, req->actual);
|
|
requeue:
|
|
requeue:
|
|
req->length = ep->maxpacket;
|
|
req->length = ep->maxpacket;
|
|
@@ -1406,23 +1388,24 @@ static int __init gs_bind(struct usb_gadget *gadget)
|
|
? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
|
|
? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
|
|
gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
|
|
gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
|
|
|
|
|
|
-#ifdef CONFIG_USB_GADGET_DUALSPEED
|
|
|
|
- gs_qualifier_desc.bDeviceClass = use_acm
|
|
|
|
- ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
|
|
|
|
- /* assume ep0 uses the same packet size for both speeds */
|
|
|
|
- gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;
|
|
|
|
- /* assume endpoints are dual-speed */
|
|
|
|
- gs_highspeed_notify_desc.bEndpointAddress =
|
|
|
|
- gs_fullspeed_notify_desc.bEndpointAddress;
|
|
|
|
- gs_highspeed_in_desc.bEndpointAddress =
|
|
|
|
- gs_fullspeed_in_desc.bEndpointAddress;
|
|
|
|
- gs_highspeed_out_desc.bEndpointAddress =
|
|
|
|
- gs_fullspeed_out_desc.bEndpointAddress;
|
|
|
|
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
|
|
|
|
|
+ if (gadget_is_dualspeed(gadget)) {
|
|
|
|
+ gs_qualifier_desc.bDeviceClass = use_acm
|
|
|
|
+ ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
|
|
|
|
+ /* assume ep0 uses the same packet size for both speeds */
|
|
|
|
+ gs_qualifier_desc.bMaxPacketSize0 =
|
|
|
|
+ gs_device_desc.bMaxPacketSize0;
|
|
|
|
+ /* assume endpoints are dual-speed */
|
|
|
|
+ gs_highspeed_notify_desc.bEndpointAddress =
|
|
|
|
+ gs_fullspeed_notify_desc.bEndpointAddress;
|
|
|
|
+ gs_highspeed_in_desc.bEndpointAddress =
|
|
|
|
+ gs_fullspeed_in_desc.bEndpointAddress;
|
|
|
|
+ gs_highspeed_out_desc.bEndpointAddress =
|
|
|
|
+ gs_fullspeed_out_desc.bEndpointAddress;
|
|
|
|
+ }
|
|
|
|
|
|
usb_gadget_set_selfpowered(gadget);
|
|
usb_gadget_set_selfpowered(gadget);
|
|
|
|
|
|
- if (gadget->is_otg) {
|
|
|
|
|
|
+ if (gadget_is_otg(gadget)) {
|
|
gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
|
|
gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
|
|
gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
@@ -1570,9 +1553,8 @@ static int gs_setup_standard(struct usb_gadget *gadget,
|
|
memcpy(req->buf, &gs_device_desc, ret);
|
|
memcpy(req->buf, &gs_device_desc, ret);
|
|
break;
|
|
break;
|
|
|
|
|
|
-#ifdef CONFIG_USB_GADGET_DUALSPEED
|
|
|
|
case USB_DT_DEVICE_QUALIFIER:
|
|
case USB_DT_DEVICE_QUALIFIER:
|
|
- if (!gadget->is_dualspeed)
|
|
|
|
|
|
+ if (!gadget_is_dualspeed(gadget))
|
|
break;
|
|
break;
|
|
ret = min(wLength,
|
|
ret = min(wLength,
|
|
(u16)sizeof(struct usb_qualifier_descriptor));
|
|
(u16)sizeof(struct usb_qualifier_descriptor));
|
|
@@ -1580,14 +1562,13 @@ static int gs_setup_standard(struct usb_gadget *gadget,
|
|
break;
|
|
break;
|
|
|
|
|
|
case USB_DT_OTHER_SPEED_CONFIG:
|
|
case USB_DT_OTHER_SPEED_CONFIG:
|
|
- if (!gadget->is_dualspeed)
|
|
|
|
|
|
+ if (!gadget_is_dualspeed(gadget))
|
|
break;
|
|
break;
|
|
/* fall through */
|
|
/* fall through */
|
|
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
|
|
|
case USB_DT_CONFIG:
|
|
case USB_DT_CONFIG:
|
|
- ret = gs_build_config_buf(req->buf, gadget->speed,
|
|
|
|
|
|
+ ret = gs_build_config_buf(req->buf, gadget,
|
|
wValue >> 8, wValue & 0xff,
|
|
wValue >> 8, wValue & 0xff,
|
|
- gadget->is_otg);
|
|
|
|
|
|
+ gadget_is_otg(gadget));
|
|
if (ret >= 0)
|
|
if (ret >= 0)
|
|
ret = min(wLength, (u16)ret);
|
|
ret = min(wLength, (u16)ret);
|
|
break;
|
|
break;
|
|
@@ -1827,8 +1808,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
|
|
|
|
|
|
if (EP_NOTIFY_NAME
|
|
if (EP_NOTIFY_NAME
|
|
&& strcmp(ep->name, EP_NOTIFY_NAME) == 0) {
|
|
&& strcmp(ep->name, EP_NOTIFY_NAME) == 0) {
|
|
- ep_desc = GS_SPEED_SELECT(
|
|
|
|
- gadget->speed == USB_SPEED_HIGH,
|
|
|
|
|
|
+ ep_desc = choose_ep_desc(gadget,
|
|
&gs_highspeed_notify_desc,
|
|
&gs_highspeed_notify_desc,
|
|
&gs_fullspeed_notify_desc);
|
|
&gs_fullspeed_notify_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
@@ -1844,9 +1824,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
|
|
}
|
|
}
|
|
|
|
|
|
else if (strcmp(ep->name, EP_IN_NAME) == 0) {
|
|
else if (strcmp(ep->name, EP_IN_NAME) == 0) {
|
|
- ep_desc = GS_SPEED_SELECT(
|
|
|
|
- gadget->speed == USB_SPEED_HIGH,
|
|
|
|
- &gs_highspeed_in_desc,
|
|
|
|
|
|
+ ep_desc = choose_ep_desc(gadget,
|
|
|
|
+ &gs_highspeed_in_desc,
|
|
&gs_fullspeed_in_desc);
|
|
&gs_fullspeed_in_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
@@ -1861,8 +1840,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
|
|
}
|
|
}
|
|
|
|
|
|
else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
|
|
else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
|
|
- ep_desc = GS_SPEED_SELECT(
|
|
|
|
- gadget->speed == USB_SPEED_HIGH,
|
|
|
|
|
|
+ ep_desc = choose_ep_desc(gadget,
|
|
&gs_highspeed_out_desc,
|
|
&gs_highspeed_out_desc,
|
|
&gs_fullspeed_out_desc);
|
|
&gs_fullspeed_out_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
ret = usb_ep_enable(ep,ep_desc);
|
|
@@ -1981,11 +1959,11 @@ static void gs_reset_config(struct gs_dev *dev)
|
|
* Builds the config descriptors in the given buffer and returns the
|
|
* Builds the config descriptors in the given buffer and returns the
|
|
* length, or a negative error number.
|
|
* length, or a negative error number.
|
|
*/
|
|
*/
|
|
-static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
|
|
|
|
|
|
+static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
|
|
u8 type, unsigned int index, int is_otg)
|
|
u8 type, unsigned int index, int is_otg)
|
|
{
|
|
{
|
|
int len;
|
|
int len;
|
|
- int high_speed;
|
|
|
|
|
|
+ int high_speed = 0;
|
|
const struct usb_config_descriptor *config_desc;
|
|
const struct usb_config_descriptor *config_desc;
|
|
const struct usb_descriptor_header **function;
|
|
const struct usb_descriptor_header **function;
|
|
|
|
|
|
@@ -1993,20 +1971,22 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
/* other speed switches high and full speed */
|
|
/* other speed switches high and full speed */
|
|
- high_speed = (speed == USB_SPEED_HIGH);
|
|
|
|
- if (type == USB_DT_OTHER_SPEED_CONFIG)
|
|
|
|
- high_speed = !high_speed;
|
|
|
|
|
|
+ if (gadget_is_dualspeed(g)) {
|
|
|
|
+ high_speed = (g->speed == USB_SPEED_HIGH);
|
|
|
|
+ if (type == USB_DT_OTHER_SPEED_CONFIG)
|
|
|
|
+ high_speed = !high_speed;
|
|
|
|
+ }
|
|
|
|
|
|
if (use_acm) {
|
|
if (use_acm) {
|
|
config_desc = &gs_acm_config_desc;
|
|
config_desc = &gs_acm_config_desc;
|
|
- function = GS_SPEED_SELECT(high_speed,
|
|
|
|
- gs_acm_highspeed_function,
|
|
|
|
- gs_acm_fullspeed_function);
|
|
|
|
|
|
+ function = high_speed
|
|
|
|
+ ? gs_acm_highspeed_function
|
|
|
|
+ : gs_acm_fullspeed_function;
|
|
} else {
|
|
} else {
|
|
config_desc = &gs_bulk_config_desc;
|
|
config_desc = &gs_bulk_config_desc;
|
|
- function = GS_SPEED_SELECT(high_speed,
|
|
|
|
- gs_bulk_highspeed_function,
|
|
|
|
- gs_bulk_fullspeed_function);
|
|
|
|
|
|
+ function = high_speed
|
|
|
|
+ ? gs_bulk_highspeed_function
|
|
|
|
+ : gs_bulk_fullspeed_function;
|
|
}
|
|
}
|
|
|
|
|
|
/* for now, don't advertise srp-only devices */
|
|
/* for now, don't advertise srp-only devices */
|