return ret;
}
+static int qc_reset_resume(struct usb_interface *iface)
+{
+ return qc_resume(iface);
+}
+
static int qcnet_bind(struct usbnet *usbnet, struct usb_interface *iface)
{
int numends;
return -EINVAL;
}
- if (iface->cur_altsetting->desc.bInterfaceNumber != 0) {
- DBG("invalid interface %d\n",
- iface->cur_altsetting->desc.bInterfaceNumber);
- return -EINVAL;
- }
-
numends = iface->cur_altsetting->desc.bNumEndpoints;
for (i = 0; i < numends; i++) {
endpoint = iface->cur_altsetting->endpoint + i;
return -EINVAL;
}
- if (usb_endpoint_dir_in(&endpoint->desc)
- && !usb_endpoint_xfer_int(&endpoint->desc)) {
+ if (usb_endpoint_is_bulk_in(&endpoint->desc))
in = endpoint;
- } else if (!usb_endpoint_dir_out(&endpoint->desc)) {
+ else if (usb_endpoint_is_bulk_out(&endpoint->desc))
out = endpoint;
- }
}
if (!in || !out) {
in->desc.bEndpointAddress,
out->desc.bEndpointAddress);
+ strcpy(usbnet->net->name, "qmi%d");
+ random_ether_addr(&usbnet->net->dev_addr[0]);
+
return 0;
}
MKVIDPID(0x05c6, 0x9225), /* Sony Gobi 2000 */
MKVIDPID(0x05c6, 0x9235), /* Top Global Gobi 2000 */
MKVIDPID(0x05c6, 0x9275), /* iRex Technologies Gobi 2000 */
+ {
+ USB_DEVICE_AND_INTERFACE_INFO(0x22B8, 0x2A70, 0xff, 0xfb, 0xff), /* Motorola Xoom */
+ .driver_info = (unsigned long)&qc_netinfo
+ },
{ }
};
EXPORT_SYMBOL_GPL(qcnet_probe);
static struct usb_driver qcusbnet = {
- .name = "QCUSBNet2k",
- .id_table = qc_vidpids,
- .probe = qcnet_probe,
- .disconnect = usbnet_disconnect,
- .suspend = qc_suspend,
- .resume = qc_resume,
+ .name = "QCUSBNet2k",
+ .id_table = qc_vidpids,
+ .probe = qcnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = qc_suspend,
+ .resume = qc_resume,
+ .reset_resume = qc_reset_resume,
.supports_autosuspend = true,
};
#define IOCTL_QMI_GET_SERVICE_FILE (0x8BE0 + 1)
#define IOCTL_QMI_GET_DEVICE_VIDPID (0x8BE0 + 2)
#define IOCTL_QMI_GET_DEVICE_MEID (0x8BE0 + 3)
+#define CDC_GET_MASK 0xFFFFll
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01A1ll
#define CDC_CONNECTION_SPEED_CHANGE 0x08000000002AA1ll
data = urb->transfer_buffer;
size = urb->actual_length;
- print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
+ if (debug)
+ print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
16, 1, data, size, true);
result = qmux_parse(&cid, data, size);
return;
} else {
if ((urb->actual_length == 8) &&
- (*(u64 *)urb->transfer_buffer == CDC_GET_ENCAPSULATED_RESPONSE)) {
+ (*(u64 *)urb->transfer_buffer & CDC_GET_MASK) ==
+ CDC_GET_ENCAPSULATED_RESPONSE) {
usb_fill_control_urb(dev->qmi.readurb, dev->usbnet->udev,
usb_rcvctrlpipe(dev->usbnet->udev, 0),
(unsigned char *)dev->qmi.readsetup,
}
} else {
DBG("ignoring invalid interrupt in packet\n");
- print_hex_dump(KERN_INFO, "QCUSBNet2k: ",
+ if (debug)
+ print_hex_dump(KERN_INFO, "QCUSBNet2k: ",
DUMP_PREFIX_OFFSET, 16, 1,
urb->transfer_buffer,
urb->actual_length, true);
int qc_startread(struct qcusbnet *dev)
{
int interval;
+ int numends;
+ int i;
+ struct usb_host_endpoint *endpoint = NULL;
if (!device_valid(dev)) {
DBG("Invalid device!\n");
dev->qmi.readsetup->type = 0xA1;
dev->qmi.readsetup->code = 1;
dev->qmi.readsetup->value = 0;
- dev->qmi.readsetup->index = 0;
+ dev->qmi.readsetup->index = dev->iface->cur_altsetting->desc.bInterfaceNumber;
dev->qmi.readsetup->len = DEFAULT_READ_URB_LENGTH;
interval = (dev->usbnet->udev->speed == USB_SPEED_HIGH) ? 7 : 3;
+ numends = dev->iface->cur_altsetting->desc.bNumEndpoints;
+ for (i = 0; i < numends; i++) {
+ endpoint = dev->iface->cur_altsetting->endpoint + i;
+ if (!endpoint) {
+ DBG("invalid endpoint %u\n", i);
+ return -EINVAL;
+ }
+
+ if (usb_endpoint_dir_in(&endpoint->desc)
+ && usb_endpoint_xfer_int(&endpoint->desc)) {
+ DBG("Interrupt endpoint is %x\n", endpoint->desc.bEndpointAddress);
+ break;
+ }
+ }
+
usb_fill_int_urb(dev->qmi.inturb, dev->usbnet->udev,
- usb_rcvintpipe(dev->usbnet->udev, 0x81),
+ usb_rcvintpipe(dev->usbnet->udev, endpoint->desc.bEndpointAddress),
dev->qmi.intbuf, DEFAULT_READ_URB_LENGTH,
int_callback, dev, interval);
+
return usb_submit_urb(dev->qmi.inturb, GFP_KERNEL);
}
setup.type = 0x21;
setup.code = 0;
setup.value = 0;
- setup.index = 0;
+ setup.index = dev->iface->cur_altsetting->desc.bInterfaceNumber;
setup.len = 0;
setup.len = size;
NULL, dev);
DBG("Actual Write:\n");
- print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
+ if (debug)
+ print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
16, 1, buf, size, true);
sema_init(&sem, 0);
return result;
}
- name = strstr(dev->usbnet->net->name, "usb");
+ name = strstr(dev->usbnet->net->name, "qmi");
if (!name) {
DBG("Bad net name: %s\n", dev->usbnet->net->name);
return -ENXIO;
}
- name += strlen("usb");
+ name += strlen("qmi");
qmiidx = simple_strtoul(name, NULL, 10);
if (qmiidx < 0) {
DBG("Bad minor number\n");
return result;
}
+/* TODO: Restore this once the ril supports it
result = usb_control_msg(dev->usbnet->udev,
usb_sndctrlpipe(dev->usbnet->udev, 0),
0x22, 0x21, 1, 0, NULL, 0, 100);
DBG("Bad SetControlLineState status %d\n", result);
return result;
}
+*/
return 0;
}