Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 35156
b: refs/heads/master
c: a1030e9
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Drake authored and John W. Linville committed Aug 14, 2006
1 parent 35fb4bc commit ecd98b8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4ceb7e9936dae67d6c553a4954fa410a99b3ea16
refs/heads/master: a1030e92c1507eb4a3c15d0a7d62987f671b609c
59 changes: 59 additions & 0 deletions trunk/drivers/net/wireless/zd1211rw/zd_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
/* "Driverless" devices that need ejecting */
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
{}
};

Expand Down Expand Up @@ -951,6 +953,55 @@ static void print_id(struct usb_device *udev)
#define print_id(udev) do { } while (0)
#endif

static int eject_installer(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *iface_desc = &intf->altsetting[0];
struct usb_endpoint_descriptor *endpoint;
unsigned char *cmd;
u8 bulk_out_ep;
int r;

/* Find bulk out endpoint */
endpoint = &iface_desc->endpoint[1].desc;
if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
(endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK) {
bulk_out_ep = endpoint->bEndpointAddress;
} else {
dev_err(&udev->dev,
"zd1211rw: Could not find bulk out endpoint\n");
return -ENODEV;
}

cmd = kzalloc(31, GFP_KERNEL);
if (cmd == NULL)
return -ENODEV;

/* USB bulk command block */
cmd[0] = 0x55; /* bulk command signature */
cmd[1] = 0x53; /* bulk command signature */
cmd[2] = 0x42; /* bulk command signature */
cmd[3] = 0x43; /* bulk command signature */
cmd[14] = 6; /* command length */

cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
cmd[19] = 0x2; /* eject disc */

dev_info(&udev->dev, "Ejecting virtual installer media...\n");
r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
cmd, 31, NULL, 2000);
kfree(cmd);
if (r)
return r;

/* At this point, the device disconnects and reconnects with the real
* ID numbers. */

usb_set_intfdata(intf, NULL);
return 0;
}

static int probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int r;
Expand All @@ -959,6 +1010,9 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)

print_id(udev);

if (id->driver_info & DEVICE_INSTALLER)
return eject_installer(intf);

switch (udev->speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
Expand Down Expand Up @@ -1024,6 +1078,11 @@ static void disconnect(struct usb_interface *intf)
struct zd_mac *mac = zd_netdev_mac(netdev);
struct zd_usb *usb = &mac->chip.usb;

/* Either something really bad happened, or we're just dealing with
* a DEVICE_INSTALLER. */
if (netdev == NULL)
return;

dev_dbg_f(zd_usb_dev(usb), "\n");

zd_netdev_disconnect(netdev);
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/zd1211rw/zd_usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
enum devicetype {
DEVICE_ZD1211 = 0,
DEVICE_ZD1211B = 1,
DEVICE_INSTALLER = 2,
};

enum endpoints {
Expand Down

0 comments on commit ecd98b8

Please sign in to comment.