void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev) { debug("%s(%p)\n", __func__, dev); stream_stop(dev); free_urbs(dev->data_urbs_in); free_urbs(dev->data_urbs_out); kfree(dev->data_cb_info); }
/*------------------------------------------------------------ 函数原型: void trigger_tty() 描述: 建立NDISTTY状态机的触发器函数,由usbnet的probe探测函数在查询 到Rm Net接口后,并成功配置完中断通道、批量数据通道以后调用, trigger_tty触发器函数内部开始初始化所有要用的内部缓冲区结构、 内部匹配数据结构、调用建立NDIS消息接口的内部过程,调用函数查 询网络是否支持QOS,并在建立成功以后注册设备文件结点。 输入: 无 输出: 成功建立消息接口后,会注册设备文件结点;否则不注册,建立失败 返回值: 无 -------------------------------------------------------------*/ int trigger_tty(void) { int i = 0; p_int_urb = NULL; connect_stat = 1; NDIS_DEBUG_MSG("trigger_tty is running!\n"); NDIS_DEBUG_MSG("bEpAddress=0x%0x, bInterval=0x%0x\n", ep_int_rmnet->bEndpointAddress, ep_int_rmnet->bInterval); /* 分配消息缓冲区 */ message_area = kmalloc(sizeof(*message_area), GFP_KERNEL); if (NULL == message_area) { printk("%s: Kmalloc the buffer failed.\n", __FUNCTION__); return -ENOMEM; } NDIS_DEBUG_MSG("alloc area ok [%d]\n", sizeof(*message_area)); /* 初始化内部变量和消息节点 */ init_dev_message_node_and_area(); /*初始化所用到链表头*/ INIT_LIST_HEAD(&free_list); /*每一个消息结点的读写缓冲区指针指向相应行坐标所指向的数组的* *SDU的起始位置,消息结点的坐标成员赋为对应的行坐标。在初始阶* 段所有的消息结点都链入空闲消息链表中。*/ for (i = 0; i < MSG_ROW; ++i) { message_node[i].p_msg_array = MEG_ROW(i); message_node[i].row_num = (unsigned int)i; list_add_tail((plisthead) & message_node[i].ptr_ndis_node, &free_list); } /* alloc urbs */ for (i = 0; i < MSG_ROW; ++i) { message_node[i].purb = usb_alloc_urb (0, GFP_KERNEL); if (!message_node[i].purb) { printk("%s - No free urbs available, i = %d\n", __FUNCTION__, i); /* free all non-null urb */ free_urbs(); //return -ENOMEM; } } /* 初始化读写节点 */ pndis_write_node = (PNDIS_NODE)&(message_node[0]); pndis_read_node = (PNDIS_NODE)&(message_node[1]); NDIS_DEBUG_MSG("trigger_tty ok\n"); return 0; }
/*------------------------------------------------------------ 函数原型: void exit_tty() 描述: 退出NDISTTY状态机的函数。目前对于退出时机的考虑主要是在无 线模块复位后,USB连接被复位,Usbnet调用disconnect方法,在 usbnet的disconnect方法中调用 exit_tty ,使NDISTTY状态机撤 销。 输入: 无 输出: 设备文件结点被注销 返回值: 无 -------------------------------------------------------------*/ int exit_tty(void) { free_urbs(); connect_stat = 0; intr_setup_flag = 0; if (NULL != message_area) { kfree(message_area); } NDIS_DEBUG_MSG("exit_tty\n"); return 0; }
static int alloc_urbs(struct atusb *atusb, int n) { struct urb *urb; while (n) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { free_urbs(atusb); return -ENOMEM; } usb_anchor_urb(urb, &atusb->idle_urbs); n--; } return 0; }
static void cleanup(struct wdm_device *desc) { usb_free_coherent(interface_to_usbdev(desc->intf), desc->wMaxPacketSize, desc->sbuf, desc->validity->transfer_dma); usb_free_coherent(interface_to_usbdev(desc->intf), desc->bMaxPacketSize0, desc->inbuf, desc->response->transfer_dma); kfree(desc->orq); kfree(desc->irq); kfree(desc->ubuf); free_urbs(desc); kfree(desc); }
static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) { int rv = -EINVAL; struct usb_device *udev = interface_to_usbdev(intf); struct wdm_device *desc; struct usb_host_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_cdc_dmm_desc *dmhd; u8 *buffer = intf->altsetting->extra; int buflen = intf->altsetting->extralen; u16 maxcom = 0; if (!buffer) goto out; while (buflen > 2) { if (buffer [1] != USB_DT_CS_INTERFACE) { dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } switch (buffer [2]) { case USB_CDC_HEADER_TYPE: break; case USB_CDC_DMM_TYPE: dmhd = (struct usb_cdc_dmm_desc *)buffer; maxcom = le16_to_cpu(dmhd->wMaxCommand); dev_dbg(&intf->dev, "Finding maximum buffer length: %d", maxcom); break; default: dev_err(&intf->dev, "Ignoring extra header, type %d, length %d\n", buffer[2], buffer[0]); break; } next_desc: buflen -= buffer[0]; buffer += buffer[0]; } rv = -ENOMEM; desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; mutex_init(&desc->lock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); desc->wMaxCommand = maxcom; /* this will be expanded and needed in hardware endianness */ desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); desc->intf = intf; INIT_WORK(&desc->rxwork, wdm_rxwork); rv = -EINVAL; iface = intf->cur_altsetting; if (iface->desc.bNumEndpoints != 1) goto err; ep = &iface->endpoint[0].desc; if (!ep || !usb_endpoint_is_int_in(ep)) goto err; desc->wMaxPacketSize = usb_endpoint_maxp(ep); desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!desc->orq) goto err; desc->irq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!desc->irq) goto err; desc->validity = usb_alloc_urb(0, GFP_KERNEL); if (!desc->validity) goto err; desc->response = usb_alloc_urb(0, GFP_KERNEL); if (!desc->response) goto err; desc->command = usb_alloc_urb(0, GFP_KERNEL); if (!desc->command) goto err; desc->ubuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); if (!desc->ubuf) goto err; desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf), desc->wMaxPacketSize, GFP_KERNEL, &desc->validity->transfer_dma); if (!desc->sbuf) goto err; desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), desc->bMaxPacketSize0, GFP_KERNEL, &desc->response->transfer_dma); if (!desc->inbuf) goto err2; usb_fill_int_urb( desc->validity, interface_to_usbdev(intf), usb_rcvintpipe(interface_to_usbdev(intf), ep->bEndpointAddress), desc->sbuf, desc->wMaxPacketSize, wdm_int_callback, desc, ep->bInterval ); desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_set_intfdata(intf, desc); rv = usb_register_dev(intf, &wdm_class); if (rv < 0) goto err3; else dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", intf->minor - WDM_MINOR_BASE); out: return rv; err3: usb_set_intfdata(intf, NULL); usb_free_coherent(interface_to_usbdev(desc->intf), desc->bMaxPacketSize0, desc->inbuf, desc->response->transfer_dma); err2: usb_free_coherent(interface_to_usbdev(desc->intf), desc->wMaxPacketSize, desc->sbuf, desc->validity->transfer_dma); err: free_urbs(desc); kfree(desc->ubuf); kfree(desc->orq); kfree(desc->irq); kfree(desc); return rv; }
int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) { int i, ret; dev->n_audio_in = max(dev->spec.num_analog_audio_in, dev->spec.num_digital_audio_in) / CHANNELS_PER_STREAM; dev->n_audio_out = max(dev->spec.num_analog_audio_out, dev->spec.num_digital_audio_out) / CHANNELS_PER_STREAM; dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); debug("dev->n_audio_in = %d\n", dev->n_audio_in); debug("dev->n_audio_out = %d\n", dev->n_audio_out); debug("dev->n_streams = %d\n", dev->n_streams); if (dev->n_streams > MAX_STREAMS) { log("unable to initialize device, too many streams.\n"); return -EINVAL; } ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, dev->n_audio_out, dev->n_audio_in, &dev->pcm); if (ret < 0) { log("snd_pcm_new() returned %d\n", ret); return ret; } dev->pcm->private_data = dev; strcpy(dev->pcm->name, dev->product_name); memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, sizeof(snd_usb_caiaq_pcm_hardware)); /* setup samplerates */ dev->samplerates = dev->pcm_info.rates; switch (dev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): dev->samplerates |= SNDRV_PCM_RATE_192000; /* fall thru */ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): dev->samplerates |= SNDRV_PCM_RATE_88200; break; } snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_caiaq_ops); snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_caiaq_ops); snd_pcm_lib_preallocate_pages_for_all(dev->pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); dev->data_cb_info = kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, GFP_KERNEL); if (!dev->data_cb_info) return -ENOMEM; for (i = 0; i < N_URBS; i++) { dev->data_cb_info[i].dev = dev; dev->data_cb_info[i].index = i; } dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); if (ret < 0) { kfree(dev->data_cb_info); free_urbs(dev->data_urbs_in); return ret; } dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); if (ret < 0) { kfree(dev->data_cb_info); free_urbs(dev->data_urbs_in); free_urbs(dev->data_urbs_out); return ret; } return 0; }