| --- ../../alsa-kernel/usb/usx2y/usx2yhwdeppcm.c 2009-09-28 12:02:26.000000000 +0200 |
| +++ usx2yhwdeppcm.c 2009-09-28 14:51:08.000000000 +0200 |
| @@ -1,3 +1,29 @@ |
| +#include "config.h" |
| +#ifdef CONFIG_HAVE_DEPRECATED_CONFIG_H |
| +#include <linux/autoconf.h> |
| +#else |
| +#include <linux/config.h> |
| +#endif |
| +#include <linux/version.h> |
| + |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) |
| +#define SND_NEED_USB_SET_INTERFACE |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) |
| +#define SND_NEED_USB_WRAPPER |
| +#endif |
| +#define __NO_VERSION__ |
| +#endif |
| + |
| +#define USB_2_6_18 (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) |
| +#if USB_2_6_18 |
| +#define USX2Y_URB_FRAME_MASK -1 |
| +#else |
| +#define USX2Y_URB_FRAME_MASK 0xffff |
| +#endif |
| + |
| +#include "adriver.h" |
| +#include "../usbcompat.h" |
| + |
| /* |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| @@ -150,7 +176,11 @@ |
| { |
| int pack; |
| for (pack = 0; pack < nr_of_packs(); ++pack) { |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20) |
| struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack; |
| +#else |
| + iso_packet_descriptor_t *desc = urb->iso_frame_desc + pack; |
| +#endif |
| if (NULL != subs) { |
| struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm; |
| int head = shm->captured_iso_head + 1; |
| @@ -226,7 +256,11 @@ |
| } |
| |
| |
| +#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER) |
| +static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs) |
| +#else |
| static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) |
| +#endif |
| { |
| struct snd_usX2Y_substream *subs = urb->context; |
| struct usX2Ydev *usX2Y = subs->usX2Y; |
| @@ -256,9 +290,15 @@ |
| if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && |
| (NULL == capsubs2 || capsubs2->completed_urb) && |
| (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { |
| - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) |
| - usX2Y->wait_iso_frame += nr_of_packs(); |
| - else { |
| + if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { |
| +#if !USB_2_6_18 |
| + if (nr_of_packs() <= urb->start_frame && |
| + urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci |
| + usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs(); |
| + else |
| +#endif |
| + usX2Y->wait_iso_frame += nr_of_packs(); |
| + } else { |
| snd_printdd("\n"); |
| usX2Y_clients_stop(usX2Y); |
| } |
| @@ -290,7 +330,11 @@ |
| usX2Y->prepare_subs = NULL; |
| } |
| |
| +#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER) |
| +static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs) |
| +#else |
| static void i_usX2Y_usbpcm_subs_startup(struct urb *urb) |
| +#endif |
| { |
| struct snd_usX2Y_substream *subs = urb->context; |
| struct usX2Ydev *usX2Y = subs->usX2Y; |
| @@ -307,7 +351,11 @@ |
| wake_up(&usX2Y->prepare_wait_queue); |
| } |
| |
| +#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER) |
| + i_usX2Y_usbpcm_urb_complete(urb, regs); |
| +#else |
| i_usX2Y_usbpcm_urb_complete(urb); |
| +#endif |
| } |
| |
| /* |
| @@ -429,6 +477,9 @@ |
| if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) |
| goto start; |
| } |
| +#if !USB_2_6_18 |
| + usX2Y->wait_iso_frame = -1; |
| +#endif |
| |
| start: |
| usX2Y_usbpcm_subs_startup(subs); |
| @@ -454,7 +505,11 @@ |
| goto cleanup; |
| } else { |
| snd_printdd("%i\n", urb->start_frame); |
| +#if USB_2_6_18 |
| if (u == 0) |
| +#else |
| + if (0 > usX2Y->wait_iso_frame) |
| +#endif |
| usX2Y->wait_iso_frame = urb->start_frame; |
| } |
| urb->transfer_flags = 0; |
| @@ -683,6 +738,7 @@ |
| } |
| |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) |
| static int snd_usX2Y_hwdep_pcm_vm_fault(struct vm_area_struct *area, |
| struct vm_fault *vmf) |
| { |
| @@ -695,12 +751,60 @@ |
| get_page(vmf->page); |
| return 0; |
| } |
| +#else /* 2.6.24 */ |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
| +static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area, |
| + unsigned long address, int *type) |
| +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) |
| +static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area, |
| + unsigned long address, int no_share) |
| +#else |
| +static unsigned long snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area, |
| + unsigned long address, int no_share) |
| +#endif |
| +{ |
| + unsigned long offset; |
| + struct page *page; |
| + void *vaddr; |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25) |
| + offset = area->vm_pgoff << PAGE_SHIFT; |
| +#else |
| + offset = area->vm_offset; |
| +#endif |
| + offset += address - area->vm_start; |
| + if (snd_BUG_ON(offset % PAGE_SIZE)) |
| + return NOPAGE_OOM; |
| + vaddr = (char*)((struct usX2Ydev *) |
| + area->vm_private_data)->hwdep_pcm_shm + offset; |
| + page = virt_to_page(vaddr); |
| +#ifndef CONFIG_SND_REMOVE_PAGE_RESERVE |
| + if (!PageReserved(page)) |
| +#endif |
| + get_page(page); |
| + |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
| + if (type) |
| + *type = VM_FAULT_MINOR; |
| +#endif |
| + |
| +#ifndef LINUX_2_2 |
| + return page; |
| +#else |
| +#undef page_address |
| + return page_address(page); |
| +#endif |
| +} |
| +#endif /* >= 2.6.24 */ |
| |
| static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { |
| .open = snd_usX2Y_hwdep_pcm_vm_open, |
| .close = snd_usX2Y_hwdep_pcm_vm_close, |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) |
| .fault = snd_usX2Y_hwdep_pcm_vm_fault, |
| +#else |
| + .nopage = snd_usX2Y_hwdep_pcm_vm_nopage, |
| +#endif |
| }; |
| |
| |
| @@ -722,8 +826,14 @@ |
| return -ENODEV; |
| } |
| area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; |
| +#ifdef VM_RESERVED |
| area->vm_flags |= VM_RESERVED | VM_DONTEXPAND; |
| +#endif |
| +#ifndef LINUX_2_2 |
| area->vm_private_data = hw->private_data; |
| +#else |
| + area->vm_private_data = (long)hw->private_data; |
| +#endif |
| return 0; |
| } |
| |