📄 speedtch.c
字号:
dbg ("udsl_atm_open: no memory for vcc_data!"); up (&instance->serialize); return -ENOMEM; } memset (new, 0, sizeof (struct udsl_vcc_data)); new->vcc = vcc; new->vpi = vpi; new->vci = vci; /* udsl_extract_cells requires at least one cell */ max_pdu = max (1, UDSL_NUM_CELLS (vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD; if (!(new->sarb = alloc_skb (max_pdu, GFP_KERNEL))) { dbg ("udsl_atm_open: no memory for SAR buffer!"); kfree (new); up (&instance->serialize); return -ENOMEM; } vcc->dev_data = new; tasklet_disable (&instance->receive_tasklet); list_add (&new->list, &instance->vcc_list); tasklet_enable (&instance->receive_tasklet); set_bit (ATM_VF_ADDR, &vcc->flags); set_bit (ATM_VF_PARTIAL, &vcc->flags); set_bit (ATM_VF_READY, &vcc->flags); up (&instance->serialize); tasklet_schedule (&instance->receive_tasklet); dbg ("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu); return 0;}static void udsl_atm_close (struct atm_vcc *vcc){ struct udsl_instance_data *instance = vcc->dev->dev_data; struct udsl_vcc_data *vcc_data = vcc->dev_data; dbg ("udsl_atm_close called"); if (!instance || !vcc_data) { dbg ("udsl_atm_close: NULL data!"); return; } dbg ("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci); udsl_cancel_send (instance, vcc); down (&instance->serialize); /* vs self, udsl_atm_open */ tasklet_disable (&instance->receive_tasklet); list_del (&vcc_data->list); tasklet_enable (&instance->receive_tasklet); kfree_skb (vcc_data->sarb); vcc_data->sarb = NULL; kfree (vcc_data); vcc->dev_data = NULL; vcc->vpi = ATM_VPI_UNSPEC; vcc->vci = ATM_VCI_UNSPEC; clear_bit (ATM_VF_READY, &vcc->flags); clear_bit (ATM_VF_PARTIAL, &vcc->flags); clear_bit (ATM_VF_ADDR, &vcc->flags); up (&instance->serialize); dbg ("udsl_atm_close successful");}static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void __user *arg){ switch (cmd) { case ATM_QUERYLOOP: return put_user (ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; default: return -ENOIOCTLCMD; }}/************ USB ************/static int udsl_set_alternate (struct udsl_instance_data *instance){ down (&instance->serialize); /* vs self */ if (!instance->firmware_loaded) { int ret; if ((ret = usb_set_interface (instance->usb_dev, 1, 1)) < 0) { dbg ("udsl_set_alternate: usb_set_interface returned %d!", ret); up (&instance->serialize); return ret; } instance->firmware_loaded = 1; } up (&instance->serialize); tasklet_schedule (&instance->receive_tasklet); return 0;}static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data){ struct udsl_instance_data *instance = usb_get_intfdata (intf); dbg ("udsl_usb_ioctl entered"); if (!instance) { dbg ("udsl_usb_ioctl: NULL instance!"); return -ENODEV; } switch (code) { case UDSL_IOCTL_LINE_UP: instance->atm_dev->signal = ATM_PHY_SIG_FOUND; return udsl_set_alternate (instance); case UDSL_IOCTL_LINE_DOWN: instance->atm_dev->signal = ATM_PHY_SIG_LOST; return 0; default: return -ENOTTY; }}static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *dev = interface_to_usbdev(intf); int ifnum = intf->altsetting->desc.bInterfaceNumber; struct udsl_instance_data *instance; unsigned char mac_str [13]; int i, length; char *buf; dbg ("udsl_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || (dev->descriptor.idVendor != SPEEDTOUCH_VENDORID) || (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1)) return -ENODEV; dbg ("udsl_usb_probe: device accepted"); /* instance init */ if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for instance data!"); return -ENOMEM; } memset (instance, 0, sizeof (struct udsl_instance_data)); init_MUTEX (&instance->serialize); instance->usb_dev = dev; INIT_LIST_HEAD (&instance->vcc_list); spin_lock_init (&instance->receive_lock); INIT_LIST_HEAD (&instance->spare_receivers); INIT_LIST_HEAD (&instance->filled_receive_buffers); tasklet_init (&instance->receive_tasklet, udsl_process_receive, (unsigned long) instance); INIT_LIST_HEAD (&instance->spare_receive_buffers); skb_queue_head_init (&instance->sndqueue); spin_lock_init (&instance->send_lock); INIT_LIST_HEAD (&instance->spare_senders); INIT_LIST_HEAD (&instance->spare_send_buffers); tasklet_init (&instance->send_tasklet, udsl_process_send, (unsigned long) instance); INIT_LIST_HEAD (&instance->filled_send_buffers); /* receive init */ for (i = 0; i < num_rcv_urbs; i++) { struct udsl_receiver *rcv = &(instance->receivers [i]); if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for receive urb %d!", i); goto fail; } rcv->instance = instance; list_add (&rcv->list, &instance->spare_receivers); } for (i = 0; i < num_rcv_bufs; i++) { struct udsl_receive_buffer *buf = &(instance->receive_buffers [i]); if (!(buf->base = kmalloc (rcv_buf_size * ATM_CELL_SIZE, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for receive buffer %d!", i); goto fail; } list_add (&buf->list, &instance->spare_receive_buffers); } /* send init */ for (i = 0; i < num_snd_urbs; i++) { struct udsl_sender *snd = &(instance->senders [i]); if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for send urb %d!", i); goto fail; } snd->instance = instance; list_add (&snd->list, &instance->spare_senders); } for (i = 0; i < num_snd_bufs; i++) { struct udsl_send_buffer *buf = &(instance->send_buffers [i]); if (!(buf->base = kmalloc (snd_buf_size * ATM_CELL_SIZE, GFP_KERNEL))) { dbg ("udsl_usb_probe: no memory for send buffer %d!", i); goto fail; } list_add (&buf->list, &instance->spare_send_buffers); } /* ATM init */ if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, NULL))) { dbg ("udsl_usb_probe: failed to register ATM device!"); goto fail; } instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; /* temp init ATM device, set to 128kbit */ instance->atm_dev->link_rate = 128 * 1000 / 424; /* set MAC address, it is stored in the serial number */ memset (instance->atm_dev->esi, 0, sizeof (instance->atm_dev->esi)); if (usb_string (dev, dev->descriptor.iSerialNumber, mac_str, sizeof (mac_str)) == 12) for (i = 0; i < 6; i++) instance->atm_dev->esi [i] = (hex2int (mac_str [i * 2]) * 16) + (hex2int (mac_str [i * 2 + 1])); /* device description */ buf = instance->description; length = sizeof (instance->description); if ((i = usb_string (dev, dev->descriptor.iProduct, buf, length)) < 0) goto finish; buf += i; length -= i; i = scnprintf (buf, length, " ("); buf += i; length -= i; if (length <= 0 || (i = usb_make_path (dev, buf, length)) < 0) goto finish; buf += i; length -= i; snprintf (buf, length, ")");finish: /* ready for ATM callbacks */ wmb (); instance->atm_dev->dev_data = instance; usb_set_intfdata (intf, instance); return 0;fail: for (i = 0; i < num_snd_bufs; i++) kfree (instance->send_buffers [i].base); for (i = 0; i < num_snd_urbs; i++) usb_free_urb (instance->senders [i].urb); for (i = 0; i < num_rcv_bufs; i++) kfree (instance->receive_buffers [i].base); for (i = 0; i < num_rcv_urbs; i++) usb_free_urb (instance->receivers [i].urb); kfree (instance); return -ENOMEM;}static void udsl_usb_disconnect (struct usb_interface *intf){ struct udsl_instance_data *instance = usb_get_intfdata (intf); struct list_head *pos; unsigned int count; int result, i; dbg ("udsl_usb_disconnect entered"); usb_set_intfdata (intf, NULL); if (!instance) { dbg ("udsl_usb_disconnect: NULL instance!"); return; } /* receive finalize */ tasklet_disable (&instance->receive_tasklet); for (i = 0; i < num_rcv_urbs; i++) if ((result = usb_unlink_urb (instance->receivers [i].urb)) < 0) dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d!", i, result); /* wait for completion handlers to finish */ do { count = 0; spin_lock_irq (&instance->receive_lock); list_for_each (pos, &instance->spare_receivers) DEBUG_ON (++count > num_rcv_urbs); spin_unlock_irq (&instance->receive_lock); dbg ("udsl_usb_disconnect: found %u spare receivers", count); if (count == num_rcv_urbs) break; set_current_state (TASK_RUNNING); schedule (); } while (1); /* no need to take the spinlock */ INIT_LIST_HEAD (&instance->filled_receive_buffers); INIT_LIST_HEAD (&instance->spare_receive_buffers); tasklet_enable (&instance->receive_tasklet); for (i = 0; i < num_rcv_urbs; i++) usb_free_urb (instance->receivers [i].urb); for (i = 0; i < num_rcv_bufs; i++) kfree (instance->receive_buffers [i].base); /* send finalize */ tasklet_disable (&instance->send_tasklet); for (i = 0; i < num_snd_urbs; i++) if ((result = usb_unlink_urb (instance->senders [i].urb)) < 0) dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d!", i, result); /* wait for completion handlers to finish */ do { count = 0; spin_lock_irq (&instance->send_lock); list_for_each (pos, &instance->spare_senders) DEBUG_ON (++count > num_snd_urbs); spin_unlock_irq (&instance->send_lock); dbg ("udsl_usb_disconnect: found %u spare senders", count); if (count == num_snd_urbs) break; set_current_state (TASK_RUNNING); schedule (); } while (1); /* no need to take the spinlock */ INIT_LIST_HEAD (&instance->spare_senders); INIT_LIST_HEAD (&instance->spare_send_buffers); instance->current_buffer = NULL; tasklet_enable (&instance->send_tasklet); for (i = 0; i < num_snd_urbs; i++) usb_free_urb (instance->senders [i].urb); for (i = 0; i < num_snd_bufs; i++) kfree (instance->send_buffers [i].base); wmb (); instance->usb_dev = NULL; /* ATM finalize */ shutdown_atm_dev (instance->atm_dev); /* frees instance, kills tasklets */}/************* init *************/static int __init udsl_usb_init (void){ dbg ("udsl_usb_init: driver version " DRIVER_VERSION); if (sizeof (struct udsl_control) > sizeof (((struct sk_buff *)0)->cb)) { printk (KERN_ERR __FILE__ ": unusable with this kernel!\n"); return -EIO; } if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) || (num_snd_urbs > UDSL_MAX_SND_URBS) || (num_rcv_bufs > UDSL_MAX_RCV_BUFS) || (num_snd_bufs > UDSL_MAX_SND_BUFS) || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) return -EINVAL; return usb_register (&udsl_usb_driver);}static void __exit udsl_usb_cleanup (void){ dbg ("udsl_usb_cleanup entered"); usb_deregister (&udsl_usb_driver);}module_init (udsl_usb_init);module_exit (udsl_usb_cleanup);MODULE_AUTHOR (DRIVER_AUTHOR);MODULE_DESCRIPTION (DRIVER_DESC);MODULE_LICENSE ("GPL");MODULE_VERSION (DRIVER_VERSION);/************** debug **************/#ifdef VERBOSE_DEBUGstatic int udsl_print_packet (const unsigned char *data, int len){ unsigned char buffer [256]; int i = 0, j = 0; for (i = 0; i < len;) { buffer [0] = '\0'; sprintf (buffer, "%.3d :", i); for (j = 0; (j < 16) && (i < len); j++, i++) { sprintf (buffer, "%s %2.2x", buffer, data [i]); } dbg ("%s", buffer); } return i;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -