* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
-// #define DEBUG // error path messages, extra info
-// #define VERBOSE // more; success messages
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
* Call context is likely probe(), before interface name is known,
* which is why we won't try to use it in the diagnostics.
*/
-int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
+int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
{
struct cdc_state *info = (void *) &dev->data;
int master_ifnum;
USB_CDC_GET_ENCAPSULATED_RESPONSE,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, master_ifnum,
- buf, CONTROL_BUFFER_SIZE,
+ buf, buflen,
RNDIS_CONTROL_TIMEOUT_MS);
if (likely(retval >= 8)) {
msg_len = le32_to_cpu(buf->msg_len);
dev_dbg(&info->control->dev,
"rndis response error, code %d\n", retval);
}
- msleep(2);
+ msleep(20);
}
dev_dbg(&info->control->dev, "rndis response timeout\n");
return -ETIMEDOUT;
* ActiveSync 4.1 Windows driver.
*/
static int rndis_query(struct usbnet *dev, struct usb_interface *intf,
- void *buf, u32 oid, u32 in_len,
+ void *buf, __le32 oid, u32 in_len,
void **reply, int *reply_len)
{
int retval;
u.get->len = cpu_to_le32(in_len);
u.get->offset = ccpu2(20);
- retval = rndis_command(dev, u.header);
+ retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE);
if (unlikely(retval < 0)) {
dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) failed, %d\n",
oid, retval);
struct rndis_set_c *set_c;
struct rndis_halt *halt;
} u;
- u32 tmp, *phym;
+ u32 tmp;
+ __le32 phym_unspec, *phym;
int reply_len;
unsigned char *bp;
net->hard_header_len += sizeof (struct rndis_data_hdr);
dev->hard_mtu = net->mtu + net->hard_header_len;
+ dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1);
+ if (dev->maxpacket == 0) {
+ if (netif_msg_probe(dev))
+ dev_dbg(&intf->dev, "dev->maxpacket can't be 0\n");
+ retval = -EINVAL;
+ goto fail_and_release;
+ }
+
dev->rx_urb_size = dev->hard_mtu + (dev->maxpacket + 1);
dev->rx_urb_size &= ~(dev->maxpacket - 1);
u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size);
net->change_mtu = NULL;
- retval = rndis_command(dev, u.header);
+ retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE);
if (unlikely(retval < 0)) {
/* it might not even be an RNDIS device!! */
dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
goto halt_fail_and_release;
/* Check physical medium */
+ phym = NULL;
reply_len = sizeof *phym;
retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM,
0, (void **) &phym, &reply_len);
- if (retval != 0)
+ if (retval != 0 || !phym) {
/* OID is optional so don't fail here. */
- *phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
+ phym_unspec = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
+ phym = &phym_unspec;
+ }
if ((flags & FLAG_RNDIS_PHYM_WIRELESS) &&
*phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
if (netif_msg_probe(dev))
u.set->offset = ccpu2((sizeof *u.set) - 8);
*(__le32 *)(u.buf + sizeof *u.set) = RNDIS_DEFAULT_FILTER;
- retval = rndis_command(dev, u.header);
+ retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE);
if (unlikely(retval < 0)) {
dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
goto halt_fail_and_release;
memset(u.halt, 0, sizeof *u.halt);
u.halt->msg_type = RNDIS_MSG_HALT;
u.halt->msg_len = ccpu2(sizeof *u.halt);
- (void) rndis_command(dev, (void *)u.halt);
+ (void) rndis_command(dev, (void *)u.halt, CONTROL_BUFFER_SIZE);
fail_and_release:
usb_set_intfdata(info->data, NULL);
usb_driver_release_interface(driver_of(intf), info->data);
if (halt) {
halt->msg_type = RNDIS_MSG_HALT;
halt->msg_len = ccpu2(sizeof *halt);
- (void) rndis_command(dev, (void *)halt);
+ (void) rndis_command(dev, (void *)halt, CONTROL_BUFFER_SIZE);
kfree(halt);
}