📄 usb-c2420eb.c
字号:
/* verify that we actually have some data to write */ if (count == 0) { dbg(__FUNCTION__ " - write request of 0 bytes"); goto exit; } /* see if we are already in the middle of a write */ if (dev->write_urb->status == -EINPROGRESS) { dbg (__FUNCTION__ " - already writing"); goto exit; } /* we can only write as much as 1 urb will hold */ bytes_written = (count > dev->bulk_out_size) ? dev->bulk_out_size : count; /* copy the data from userspace into our urb */ if (copy_from_user(dev->write_urb->transfer_buffer, buffer, bytes_written)) { retval = -EFAULT; goto exit; } c2420eb_debug_data (__FUNCTION__, bytes_written, dev->write_urb->transfer_buffer); /* set up our urb */ FILL_BULK_URB(dev->write_urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), dev->write_urb->transfer_buffer, bytes_written, c2420eb_write_bulk_callback, dev); /* send the data out the bulk port */ retval = usb_submit_urb(dev->write_urb); if (retval) { err(__FUNCTION__ " - failed submitting write urb, error %d", retval); } else retval = bytes_written;exit: /* unlock the device */ up (&dev->sem); return retval;}/** * c2420eb_ioctl * Function performs ioctl function call * Param: inode - special file inode description * Param: file - file description * Param: cmd - ioctl command * Param: arg - argument * Return 0 on success, -<error code> on error */static int c2420eb_ioctl (struct inode* inode, struct file* file, unsigned int cmd, unsigned long arg){ struct c2420eb* dev; //device descriptor int retval; //function return value __u16 chan; //channel number __u16 reg; //register we read/write dev = (struct c2420eb*)file->private_data; if (_IOC_TYPE(cmd) != ZB_MAGIC) return -ENOTTY; /* lock this object */ down (&dev->sem); /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { up (&dev->sem); return -ENODEV; } dbg(__FUNCTION__ " - minor %d, cmd 0x%.4x, arg %ld", dev->minor, cmd, arg); switch (cmd) { case CC2420_TRX_OFF: { retval = c2420eb_trxOff(dev); break; } case CC2420_SET_CHANNEL: { retval = __get_user(chan, (__u16*)arg); if (retval != 0) retval = -EFAULT; else { retval = c2420eb_setCahnnel(dev, chan); if ((retval = c2420_submitReadUrb(dev, 0)) < 0) { err("Open: unable submit URB %d", retval); up (&dev->sem); return -EIO; } else { dbg("Submit buffer %d", dev->writeIdx); } } break; } case CC2420_SET_MODULATION: { retval = __get_user(chan, (__u16*)arg); if (retval != 0) retval = -EFAULT; else { retval = c2420eb_readReg(dev, MDMCTRL1, ®); if (retval < 0) break; if (chan != 0) reg |= MODULATION_REVERSED; else reg &= ~MODULATION_REVERSED; retval = c2420eb_writeReg(dev, MDMCTRL1, reg); if (retval < 0) break; } break; } default: { retval = -ENOTTY; break; } } /* fill in your device specific stuff here */ /* unlock the device */ up (&dev->sem); /* return that we did not understand this ioctl call */ return retval;}/** * c2420eb_write_bulk_callback */static void c2420eb_write_bulk_callback (struct urb* urb){ struct c2420eb* dev = (struct c2420eb*)urb->context; dbg(__FUNCTION__ " - minor %d", dev->minor); if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); return; } return;}/** * c2420eb_probe * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */static void * c2420eb_probe(struct usb_device* udev, unsigned int ifnum, const struct usb_device_id* id){ struct c2420eb *dev = NULL; struct usb_interface *interface; struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; int minor; int buffer_size; int i; char name[10]; bool loadFirmware; //if we are loading firmware /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != C2420EB_VENDOR_ID) || ((udev->descriptor.idProduct != C2420EB_PRODUCT_ID) && udev->descriptor.idProduct != C2420EB_PRODUCT_ID1)) { return NULL; } if (udev->descriptor.idProduct == C2420EB_PRODUCT_ID) loadFirmware = TRUE; else loadFirmware = FALSE; /* select a "subminor" number (part of a minor number) */ down (&minor_table_mutex); for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } if (minor >= MAX_DEVICES) { info ("Too many devices plugged in, can not handle this device."); goto exit; } /* allocate memory for our device state and intialize it */ dev = kmalloc (sizeof(struct c2420eb), GFP_KERNEL); if (dev == NULL) { err ("Out of memory"); goto exit; } memset (dev, 0x00, sizeof (*dev)); minor_table[minor] = dev; interface = &udev->actconfig->interface[ifnum]; init_MUTEX (&dev->sem); dev->udev = udev; dev->interface = interface; dev->minor = minor; dev->readBufSize = sizeof(dev->read_buffer) / sizeof(struct RdBuf); init_waitqueue_head (&dev->readwq); spin_lock_init(&dev->readLock); /* set up the endpoint information */ /* check out the endpoints */ if (loadFirmware) iface_desc = &interface->altsetting[1]; else iface_desc = &interface->altsetting[0]; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i]; if (endpoint->bEndpointAddress == PACKET_READ_PIPE) { dev->readLen = endpoint->wMaxPacketSize; dbg("Max packet length for read operations - %d", dev->readLen); } if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02) && dev->bulk_in_size < endpoint->wMaxPacketSize) { if (!loadFirmware && !dev->read_urb) { dev->read_urb = usb_alloc_urb(0); if (!dev->read_urb) { err("No free urbs available"); goto error; } dbg("Allocate read URB %p", dev->read_urb); } /* we found a bulk in endpoint */ buffer_size = endpoint->wMaxPacketSize; dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dbg("Allocate %d bytes for IN endpoint 0x%x", dev->bulk_in_size, endpoint->bEndpointAddress); } if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 3) == 0x02) && dev->bulk_out_size < endpoint->wMaxPacketSize) { /* we found a bulk out endpoint */ if (!dev->write_urb) { dev->write_urb = usb_alloc_urb(0); if (!dev->write_urb) { err("No free urbs available"); goto error; } dbg("Allocate write URB %p", dev->write_urb); } buffer_size = endpoint->wMaxPacketSize; dev->bulk_out_size = buffer_size; dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; dbg("Allocate %d bytes for OUT endpoint 0x%x", dev->bulk_out_size, endpoint->bEndpointAddress); } } if (dev->bulk_in_size) { dev->bulk_in_buffer = kmalloc (dev->bulk_in_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { err("Couldn't allocate bulk_in_buffer"); goto error; } dbg("Bulk in buffer of %d bytes allocated: %p", dev->bulk_in_size, dev->bulk_in_buffer); if (!loadFirmware) { for (i = 0; i < dev->readBufSize; i++) { dev->read_buffer[i].buf = kmalloc (dev->bulk_in_size, GFP_KERNEL); if (!dev->read_buffer[i].buf) { err("Couldn't allocate read_buffer"); goto error; } dbg("Bulk in buffer of %d bytes allocated: %p", dev->bulk_in_size, dev->read_buffer[i].buf); } } } if (dev->bulk_out_size) { dev->bulk_out_buffer = kmalloc (dev->bulk_out_size, GFP_KERNEL); if (!dev->bulk_out_buffer) { err("Couldn't allocate bulk_out_buffer"); goto error; } dbg("Bulk out buffer of %d bytes allocated: %p", dev->bulk_out_size, dev->bulk_out_buffer); } /* initialize the devfs node for this device and register it */ sprintf(name, "c2420eb%d", dev->minor); dev->devfs = devfs_register (usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR + 1, USB_C2420EB_MINOR_BASE + dev->minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, &c2420eb_fops, NULL); /* let the user know what node this device is now attached to */ info ("USB C2420EB device now attached to C2420EB%d", dev->minor); info ("Setting configuration"); if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) { err ("set config failed"); goto error; } //Load the firmware section if (udev->descriptor.idProduct == C2420EB_PRODUCT_ID) { // Set interface dbg("Setting interface #0, alt #1"); if (usb_set_interface(dev->udev, 0, 1) < 0) { err("Set interface error"); goto error; } if (c2420eb_initdevice(dev) < 0) { err ("Device initialization failed"); goto error; } } //Operational mode else { c2420eb_dev_proc_create(dev); if (c2420eb_mkoper(dev) < 0) goto error; } goto exit;error: c2420eb_dev_proc_destroy(dev); c2420eb_delete (dev); dev = NULL;exit: up (&minor_table_mutex); return dev;}/** * c2420eb_disconnect * * Called by the usb core when the device is removed from the system. */static void c2420eb_disconnect(struct usb_device* udev, void* ptr){ struct c2420eb* dev; int minor; dev = (struct c2420eb*)ptr; down (&minor_table_mutex); down (&dev->sem); minor = dev->minor; if (udev->descriptor.idProduct == C2420EB_PRODUCT_ID1) c2420eb_dev_proc_destroy(dev); /* remove our devfs node */ devfs_unregister(dev->devfs); /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { del_timer(&dev->reset_timer); up (&dev->sem); c2420eb_delete (dev); } else { dev->udev = NULL; up (&dev->sem); } info("USB C2420EB #%d now disconnected", minor); up (&minor_table_mutex);}/** * c2420eb_init */static int __init c2420eb_init(void){ int result;#ifdef CONFIG_PROC_FS result = c2420eb_proc_create(); if (result < 0) { err("Unable to create proc entry. Error number %d", result); usb_deregister(&c2420eb_driver); return -1; } #endif /* CONFIG_PROC_FS */ /* register this driver with the USB subsystem */ result = usb_register(&c2420eb_driver); if (result < 0) { err("usb_register failed for the "__FILE__" driver. Error number %d", result); return -1; } info(DRIVER_DESC " " DRIVER_VERSION); return 0;}/** * c2420eb_exit */static void __exit c2420eb_exit(void){ /* deregister this driver with the USB subsystem */ c2420eb_proc_destroy(); usb_deregister(&c2420eb_driver);}module_init (c2420eb_init);module_exit (c2420eb_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -