/* Structure to hold all of our device specific stuff */ struct usb_yurex { struct usb_device *udev; struct usb_interface *interface;
__u8 int_in_endpointAddr; struct urb *urb; /* URB for interrupt in */ unsignedchar *int_buffer; /* buffer for intterupt in */ struct urb *cntl_urb; /* URB for control msg */ struct usb_ctrlrequest *cntl_req; /* req for control msg */ unsignedchar *cntl_buffer; /* buffer for control msg */
staticvoid yurex_control_callback(struct urb *urb)
{ struct usb_yurex *dev = urb->context; int status = urb->status;
if (status) {
dev_err(&urb->dev->dev, "%s - control failed: %d\n",
__func__, status);
wake_up_interruptible(&dev->waitq); return;
} /* on success, sender woken up by CMD_ACK int in, or timeout */
}
/* * usb class driver info in order to get a minor number from the usb core, * and to have the device registered with the driver core
*/ staticstruct usb_class_driver yurex_class = {
.name = "yurex%d",
.fops = &yurex_fops,
.minor_base = YUREX_MINOR_BASE,
};
staticvoid yurex_interrupt(struct urb *urb)
{ struct usb_yurex *dev = urb->context; unsignedchar *buf = dev->int_buffer; int status = urb->status; unsignedlong flags; int retval, i;
switch (status) { case 0: /*success*/ break; /* The device is terminated or messed up, give up */ case -EOVERFLOW:
dev_err(&dev->interface->dev, "%s - overflow with length %d, actual length is %d\n",
__func__, YUREX_BUF_SIZE, dev->urb->actual_length); return; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: case -EILSEQ: case -EPROTO: case -ETIME: return; default:
dev_err(&dev->interface->dev, "%s - unknown status received: %d\n", __func__, status); return;
}
/* handle received message */ switch (buf[0]) { case CMD_COUNT: case CMD_READ: if (buf[6] == CMD_EOF) {
spin_lock_irqsave(&dev->lock, flags);
dev->bbu = 0; for (i = 1; i < 6; i++) {
dev->bbu += buf[i]; if (i != 5)
dev->bbu <<= 8;
}
dev_dbg(&dev->interface->dev, "%s count: %lld\n",
__func__, dev->bbu);
spin_unlock_irqrestore(&dev->lock, flags);
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
} else
dev_dbg(&dev->interface->dev, "data format error - no EOF\n"); break; case CMD_ACK:
dev_dbg(&dev->interface->dev, "%s ack: %c\n",
__func__, buf[1]);
wake_up_interruptible(&dev->waitq); break;
}
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) goto error;
kref_init(&dev->kref);
mutex_init(&dev->io_mutex);
spin_lock_init(&dev->lock);
init_waitqueue_head(&dev->waitq);
/* set up the endpoint information */
iface_desc = interface->cur_altsetting;
res = usb_find_int_in_endpoint(iface_desc, &endpoint); if (res) {
dev_err(&interface->dev, "Could not find endpoints\n");
retval = res; goto error;
}
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
dev->bbu = -1;
/* we can register the device now, as it is ready */
retval = usb_register_dev(interface, &yurex_class); if (retval) {
dev_err(&interface->dev, "Not able to get a minor for this device.\n");
usb_set_intfdata(interface, NULL); goto error;
}
dev_info(&interface->dev, "USB YUREX device now attached to Yurex #%d\n",
interface->minor);
return 0;
error: if (dev) /* this frees allocated memory */
kref_put(&dev->kref, yurex_delete); return retval;
}
staticvoid yurex_disconnect(struct usb_interface *interface)
{ struct usb_yurex *dev; int minor = interface->minor;
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &yurex_class);
/* prevent more I/O from starting */
usb_poison_urb(dev->urb);
usb_poison_urb(dev->cntl_urb);
mutex_lock(&dev->io_mutex);
dev->disconnected = 1;
mutex_unlock(&dev->io_mutex);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.