blob: 234133a505bc013ff7072319391ed8c439ca4209 [file] [log] [blame]
--- ../../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;
}