📄 ub.c
字号:
int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber; unsigned char *p; enum { ALLOC_SIZE = 1 }; struct usb_ctrlrequest *cr; struct completion compl; struct timer_list timer; int nluns; int rc; init_completion(&compl); rc = -ENOMEM; if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; *p = 55; cr = &sc->work_cr; cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; cr->bRequest = US_BULK_GET_MAX_LUN; cr->wValue = cpu_to_le16(0); cr->wIndex = cpu_to_le16(ifnum); cr->wLength = cpu_to_le16(1); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe, (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) goto err_submit; init_timer(&timer); timer.function = ub_probe_timeout; timer.data = (unsigned long) &compl; timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&timer); wait_for_completion(&compl); del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); if ((rc = sc->work_urb.status) < 0) goto err_io; if (sc->work_urb.actual_length != 1) { nluns = 0; } else { if ((nluns = *p) == 55) { nluns = 0; } else { /* GetMaxLUN returns the maximum LUN number */ nluns += 1; if (nluns > UB_MAX_LUNS) nluns = UB_MAX_LUNS; } } kfree(p); return nluns;err_io:err_submit: kfree(p);err_alloc: return rc;}/* * Clear initial stalls. */static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe){ int endp; struct usb_ctrlrequest *cr; struct completion compl; struct timer_list timer; int rc; init_completion(&compl); endp = usb_pipeendpoint(stalled_pipe); if (usb_pipein (stalled_pipe)) endp |= USB_DIR_IN; cr = &sc->work_cr; cr->bRequestType = USB_RECIP_ENDPOINT; cr->bRequest = USB_REQ_CLEAR_FEATURE; cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); cr->wIndex = cpu_to_le16(endp); cr->wLength = cpu_to_le16(0); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { printk(KERN_WARNING "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); return rc; } init_timer(&timer); timer.function = ub_probe_timeout; timer.data = (unsigned long) &compl; timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&timer); wait_for_completion(&compl); del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); /* reset the endpoint toggle */ usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0); return 0;}/* * Get the pipe settings. */static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, struct usb_interface *intf){ struct usb_host_interface *altsetting = intf->cur_altsetting; struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep; int i; /* * Find the endpoints we need. * We are expecting a minimum of 2 endpoints - in and out (bulk). * We will ignore any others. */ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ if (ep->bEndpointAddress & USB_DIR_IN) { if (ep_in == NULL) ep_in = ep; } else { if (ep_out == NULL) ep_out = ep; } } } if (ep_in == NULL || ep_out == NULL) { printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name); return -ENODEV; } /* Calculate and store the pipe values */ sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); return 0;}/* * Probing is done in the process context, which allows us to cheat * and not to build a state machine for the discovery. */static int ub_probe(struct usb_interface *intf, const struct usb_device_id *dev_id){ struct ub_dev *sc; int nluns; int rc; int i; if (usb_usual_check_type(dev_id, USB_US_TYPE_UB)) return -ENXIO; rc = -ENOMEM; if ((sc = kzalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; sc->lock = ub_next_lock(); INIT_LIST_HEAD(&sc->luns); usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); INIT_WORK(&sc->reset_work, ub_reset_task); init_waitqueue_head(&sc->reset_wait); init_timer(&sc->work_timer); sc->work_timer.data = (unsigned long) sc; sc->work_timer.function = ub_urb_timeout; ub_init_completion(&sc->work_done); sc->work_done.done = 1; /* A little yuk, but oh well... */ sc->dev = interface_to_usbdev(intf); sc->intf = intf; // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, sc); usb_get_dev(sc->dev); /* * Since we give the interface struct to the block level through * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent * oopses on close after a disconnect (kernels 2.6.16 and up). */ usb_get_intf(sc->intf); snprintf(sc->name, 12, DRV_NAME "(%d.%d)", sc->dev->bus->busnum, sc->dev->devnum); /* XXX Verify that we can handle the device (from descriptors) */ if (ub_get_pipes(sc, sc->dev, intf) != 0) goto err_dev_desc; /* * At this point, all USB initialization is done, do upper layer. * We really hate halfway initialized structures, so from the * invariants perspective, this ub_dev is fully constructed at * this point. */ /* * This is needed to clear toggles. It is a problem only if we do * `rmmod ub && modprobe ub` without disconnects, but we like that. */#if 0 /* iPod Mini fails if we do this (big white iPod works) */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe);#endif /* * The way this is used by the startup code is a little specific. * A SCSI check causes a USB stall. Our common case code sees it * and clears the check, after which the device is ready for use. * But if a check was not present, any command other than * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE). * * If we neglect to clear the SCSI check, the first real command fails * (which is the capacity readout). We clear that and retry, but why * causing spurious retries for no reason. * * Revalidation may start with its own TEST_UNIT_READY, but that one * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ for (i = 0; i < 3; i++) { /* Retries for the schwag key from KS'04 */ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break; if (rc != 0x6) break; msleep(10); } nluns = 1; for (i = 0; i < 3; i++) { if ((rc = ub_sync_getmaxlun(sc)) < 0) break; if (rc != 0) { nluns = rc; break; } msleep(100); } for (i = 0; i < nluns; i++) { ub_probe_lun(sc, i); } return 0;err_dev_desc: usb_set_intfdata(intf, NULL); usb_put_intf(sc->intf); usb_put_dev(sc->dev); kfree(sc);err_core: return rc;}static int ub_probe_lun(struct ub_dev *sc, int lnum){ struct ub_lun *lun; struct request_queue *q; struct gendisk *disk; int rc; rc = -ENOMEM; if ((lun = kzalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) goto err_alloc; lun->num = lnum; rc = -ENOSR; if ((lun->id = ub_id_get()) == -1) goto err_id; lun->udev = sc; snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)", lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num); lun->removable = 1; /* XXX Query this from the device */ lun->changed = 1; /* ub_revalidate clears only */ ub_revalidate(sc, lun); rc = -ENOMEM; if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL) goto err_diskalloc; sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); disk->major = UB_MAJOR; disk->first_minor = lun->id * UB_PARTS_PER_LUN; disk->fops = &ub_bd_fops; disk->private_data = lun; disk->driverfs_dev = &sc->intf->dev; rc = -ENOMEM; if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); blk_queue_max_hw_segments(q, UB_MAX_REQ_SG); blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */ blk_queue_max_sectors(q, UB_MAX_SECTORS); blk_queue_hardsect_size(q, lun->capacity.bsize); lun->disk = disk; q->queuedata = lun; list_add(&lun->link, &sc->luns); set_capacity(disk, lun->capacity.nsec); if (lun->removable) disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); return 0;err_blkqinit: put_disk(disk);err_diskalloc: ub_id_put(lun->id);err_id: kfree(lun);err_alloc: return rc;}static void ub_disconnect(struct usb_interface *intf){ struct ub_dev *sc = usb_get_intfdata(intf); struct ub_lun *lun; unsigned long flags; /* * Prevent ub_bd_release from pulling the rug from under us. * XXX This is starting to look like a kref. * XXX Why not to take this ref at probe time? */ spin_lock_irqsave(&ub_lock, flags); sc->openc++; spin_unlock_irqrestore(&ub_lock, flags); /* * Fence stall clearnings, operations triggered by unlinkings and so on. * We do not attempt to unlink any URBs, because we do not trust the * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway. */ atomic_set(&sc->poison, 1); /* * Wait for reset to end, if any. */ wait_event(sc->reset_wait, !sc->reset); /* * Blow away queued commands. * * Actually, this never works, because before we get here * the HCD terminates outstanding URB(s). It causes our * SCSI command queue to advance, commands fail to submit, * and the whole queue drains. So, we just use this code to * print warnings. */ spin_lock_irqsave(sc->lock, flags); { struct ub_scsi_cmd *cmd; int cnt = 0; while ((cmd = ub_cmdq_peek(sc)) != NULL) { cmd->error = -ENOTCONN; cmd->state = UB_CMDST_DONE; ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); cnt++; } if (cnt != 0) { printk(KERN_WARNING "%s: " "%d was queued after shutdown\n", sc->name, cnt); } } spin_unlock_irqrestore(sc->lock, flags); /* * Unregister the upper layer. */ list_for_each_entry(lun, &sc->luns, link) { del_gendisk(lun->disk); /* * I wish I could do: * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags); * As it is, we rely on our internal poisoning and let * the upper levels to spin furiously failing all the I/O. */ } /* * Testing for -EINPROGRESS is always a bug, so we are bending * the rules a little. */ spin_lock_irqsave(sc->lock, flags); if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */ printk(KERN_WARNING "%s: " "URB is active after disconnect\n", sc->name); } spin_unlock_irqrestore(sc->lock, flags); /* * There is virtually no chance that other CPU runs times so long * after ub_urb_complete should have called del_timer, but only if HCD * didn't forget to deliver a callback on unlink. */ del_timer_sync(&sc->work_timer); /* * At this point there must be no commands coming from anyone * and no URBs left in transit. */ ub_put(sc);}static struct usb_driver ub_driver = { .name = "ub", .probe = ub_probe, .disconnect = ub_disconnect, .id_table = ub_usb_ids,};static int __init ub_init(void){ int rc; int i; for (i = 0; i < UB_QLOCK_NUM; i++) spin_lock_init(&ub_qlockv[i]); if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; if ((rc = usb_register(&ub_driver)) != 0) goto err_register; usb_usual_set_present(USB_US_TYPE_UB); return 0;err_register: unregister_blkdev(UB_MAJOR, DRV_NAME);err_regblkdev: return rc;}static void __exit ub_exit(void){ usb_deregister(&ub_driver); unregister_blkdev(UB_MAJOR, DRV_NAME); usb_usual_clear_present(USB_US_TYPE_UB);}module_init(ub_init);module_exit(ub_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -