~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to sound/usb/6fire/comm.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Linux driver for TerraTec DMX 6Fire USB
 
3
 *
 
4
 * Device communications
 
5
 *
 
6
 * Author:      Torsten Schenk <torsten.schenk@zoho.com>
 
7
 * Created:     Jan 01, 2011
 
8
 * Version:     0.3.0
 
9
 * Copyright:   (C) Torsten Schenk
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 */
 
16
 
 
17
#include "comm.h"
 
18
#include "chip.h"
 
19
#include "midi.h"
 
20
 
 
21
enum {
 
22
        COMM_EP = 1,
 
23
        COMM_FPGA_EP = 2
 
24
};
 
25
 
 
26
static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
 
27
                u8 *buffer, void *context, void(*handler)(struct urb *urb))
 
28
{
 
29
        usb_init_urb(urb);
 
30
        urb->transfer_buffer = buffer;
 
31
        urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
 
32
        urb->complete = handler;
 
33
        urb->context = context;
 
34
        urb->interval = 1;
 
35
        urb->dev = rt->chip->dev;
 
36
}
 
37
 
 
38
static void usb6fire_comm_receiver_handler(struct urb *urb)
 
39
{
 
40
        struct comm_runtime *rt = urb->context;
 
41
        struct midi_runtime *midi_rt = rt->chip->midi;
 
42
 
 
43
        if (!urb->status) {
 
44
                if (rt->receiver_buffer[0] == 0x10) /* midi in event */
 
45
                        if (midi_rt)
 
46
                                midi_rt->in_received(midi_rt,
 
47
                                                rt->receiver_buffer + 2,
 
48
                                                rt->receiver_buffer[1]);
 
49
        }
 
50
 
 
51
        if (!rt->chip->shutdown) {
 
52
                urb->status = 0;
 
53
                urb->actual_length = 0;
 
54
                if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
 
55
                        snd_printk(KERN_WARNING PREFIX
 
56
                                        "comm data receiver aborted.\n");
 
57
        }
 
58
}
 
59
 
 
60
static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
 
61
                u8 reg, u8 vl, u8 vh)
 
62
{
 
63
        buffer[0] = 0x01;
 
64
        buffer[2] = request;
 
65
        buffer[3] = id;
 
66
        switch (request) {
 
67
        case 0x02:
 
68
                buffer[1] = 0x05; /* length (starting at buffer[2]) */
 
69
                buffer[4] = reg;
 
70
                buffer[5] = vl;
 
71
                buffer[6] = vh;
 
72
                break;
 
73
 
 
74
        case 0x12:
 
75
                buffer[1] = 0x0b; /* length (starting at buffer[2]) */
 
76
                buffer[4] = 0x00;
 
77
                buffer[5] = 0x18;
 
78
                buffer[6] = 0x05;
 
79
                buffer[7] = 0x00;
 
80
                buffer[8] = 0x01;
 
81
                buffer[9] = 0x00;
 
82
                buffer[10] = 0x9e;
 
83
                buffer[11] = reg;
 
84
                buffer[12] = vl;
 
85
                break;
 
86
 
 
87
        case 0x20:
 
88
        case 0x21:
 
89
        case 0x22:
 
90
                buffer[1] = 0x04;
 
91
                buffer[4] = reg;
 
92
                buffer[5] = vl;
 
93
                break;
 
94
        }
 
95
}
 
96
 
 
97
static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
 
98
{
 
99
        int ret;
 
100
        int actual_len;
 
101
 
 
102
        ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
 
103
                        buffer, buffer[1] + 2, &actual_len, HZ);
 
104
        if (ret < 0)
 
105
                return ret;
 
106
        else if (actual_len != buffer[1] + 2)
 
107
                return -EIO;
 
108
        return 0;
 
109
}
 
110
 
 
111
static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
 
112
                u8 reg, u8 value)
 
113
{
 
114
        u8 buffer[13]; /* 13: maximum length of message */
 
115
 
 
116
        usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
 
117
        return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
 
118
}
 
119
 
 
120
static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
 
121
                u8 reg, u8 vl, u8 vh)
 
122
{
 
123
        u8 buffer[13]; /* 13: maximum length of message */
 
124
 
 
125
        usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
 
126
        return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
 
127
}
 
128
 
 
129
int __devinit usb6fire_comm_init(struct sfire_chip *chip)
 
130
{
 
131
        struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
 
132
                        GFP_KERNEL);
 
133
        struct urb *urb = &rt->receiver;
 
134
        int ret;
 
135
 
 
136
        if (!rt)
 
137
                return -ENOMEM;
 
138
 
 
139
        rt->serial = 1;
 
140
        rt->chip = chip;
 
141
        usb_init_urb(urb);
 
142
        rt->init_urb = usb6fire_comm_init_urb;
 
143
        rt->write8 = usb6fire_comm_write8;
 
144
        rt->write16 = usb6fire_comm_write16;
 
145
 
 
146
        /* submit an urb that receives communication data from device */
 
147
        urb->transfer_buffer = rt->receiver_buffer;
 
148
        urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
 
149
        urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
 
150
        urb->dev = chip->dev;
 
151
        urb->complete = usb6fire_comm_receiver_handler;
 
152
        urb->context = rt;
 
153
        urb->interval = 1;
 
154
        ret = usb_submit_urb(urb, GFP_KERNEL);
 
155
        if (ret < 0) {
 
156
                kfree(rt);
 
157
                snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
 
158
                return ret;
 
159
        }
 
160
        chip->comm = rt;
 
161
        return 0;
 
162
}
 
163
 
 
164
void usb6fire_comm_abort(struct sfire_chip *chip)
 
165
{
 
166
        struct comm_runtime *rt = chip->comm;
 
167
 
 
168
        if (rt)
 
169
                usb_poison_urb(&rt->receiver);
 
170
}
 
171
 
 
172
void usb6fire_comm_destroy(struct sfire_chip *chip)
 
173
{
 
174
        kfree(chip->comm);
 
175
        chip->comm = NULL;
 
176
}