2 * Line6 Linux USB driver - 0.8.0
4 * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
14 #include <linux/slab.h>
19 static int midibuf_message_length(unsigned char code
)
23 else if (code
< 0xf0) {
24 static const int length
[] = { 3, 3, 3, 3, 2, 2, 3 };
25 return length
[(code
>> 4) - 8];
28 Note that according to the MIDI specification 0xf2 is
29 the "Song Position Pointer", but this is used by Line6
30 to send sysex messages to the host.
32 static const int length
[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,
34 return length
[code
& 0x0f];
38 void midibuf_reset(struct MidiBuffer
*this)
40 this->pos_read
= this->pos_write
= this->full
= 0;
41 this->command_prev
= -1;
44 int midibuf_init(struct MidiBuffer
*this, int size
, int split
)
46 this->buf
= kmalloc(size
, GFP_KERNEL
);
48 if (this->buf
== NULL
)
57 void midibuf_status(struct MidiBuffer
*this)
59 printk(KERN_DEBUG
"midibuf size=%d split=%d pos_read=%d pos_write=%d "
60 "full=%d command_prev=%02x\n", this->size
, this->split
,
61 this->pos_read
, this->pos_write
, this->full
, this->command_prev
);
64 static int midibuf_is_empty(struct MidiBuffer
*this)
66 return (this->pos_read
== this->pos_write
) && !this->full
;
69 static int midibuf_is_full(struct MidiBuffer
*this)
74 int midibuf_bytes_free(struct MidiBuffer
*this)
77 midibuf_is_full(this) ?
79 (this->pos_read
- this->pos_write
+ this->size
- 1) % this->size
+ 1;
82 int midibuf_bytes_used(struct MidiBuffer
*this)
85 midibuf_is_empty(this) ?
87 (this->pos_write
- this->pos_read
+ this->size
- 1) % this->size
+ 1;
90 int midibuf_write(struct MidiBuffer
*this, unsigned char *data
, int length
)
94 int skip_active_sense
= 0;
96 if (midibuf_is_full(this) || (length
<= 0))
99 /* skip trailing active sense */
100 if (data
[length
- 1] == 0xfe) {
102 skip_active_sense
= 1;
105 bytes_free
= midibuf_bytes_free(this);
107 if (length
> bytes_free
)
111 length1
= this->size
- this->pos_write
;
113 if (length
< length1
) {
114 /* no buffer wraparound */
115 memcpy(this->buf
+ this->pos_write
, data
, length
);
116 this->pos_write
+= length
;
118 /* buffer wraparound */
119 length2
= length
- length1
;
120 memcpy(this->buf
+ this->pos_write
, data
, length1
);
121 memcpy(this->buf
, data
+ length1
, length2
);
122 this->pos_write
= length2
;
125 if (this->pos_write
== this->pos_read
)
129 return length
+ skip_active_sense
;
132 int midibuf_read(struct MidiBuffer
*this, unsigned char *data
, int length
)
135 int length1
, length2
;
141 /* we need to be able to store at least a 3 byte MIDI message */
145 if (midibuf_is_empty(this))
148 bytes_used
= midibuf_bytes_used(this);
150 if (length
> bytes_used
)
153 length1
= this->size
- this->pos_read
;
155 /* check MIDI command length */
156 command
= this->buf
[this->pos_read
];
158 if (command
& 0x80) {
159 midi_length
= midibuf_message_length(command
);
160 this->command_prev
= command
;
162 if (this->command_prev
> 0) {
163 int midi_length_prev
= midibuf_message_length(this->command_prev
);
165 if (midi_length_prev
> 0) {
166 midi_length
= midi_length_prev
- 1;
174 if (midi_length
< 0) {
175 /* search for end of message */
176 if (length
< length1
) {
177 /* no buffer wraparound */
178 for (i
= 1; i
< length
; ++i
)
179 if (this->buf
[this->pos_read
+ i
] & 0x80)
184 /* buffer wraparound */
185 length2
= length
- length1
;
187 for (i
= 1; i
< length1
; ++i
)
188 if (this->buf
[this->pos_read
+ i
] & 0x80)
194 for (i
= 0; i
< length2
; ++i
)
195 if (this->buf
[i
] & 0x80)
198 midi_length
= length1
+ i
;
202 if (midi_length
== length
)
203 midi_length
= -1; /* end of message not found */
206 if (midi_length
< 0) {
208 return 0; /* command is not yet complete */
210 if (length
< midi_length
)
211 return 0; /* command is not yet complete */
213 length
= midi_length
;
216 if (length
< length1
) {
217 /* no buffer wraparound */
218 memcpy(data
+ repeat
, this->buf
+ this->pos_read
, length
);
219 this->pos_read
+= length
;
221 /* buffer wraparound */
222 length2
= length
- length1
;
223 memcpy(data
+ repeat
, this->buf
+ this->pos_read
, length1
);
224 memcpy(data
+ repeat
+ length1
, this->buf
, length2
);
225 this->pos_read
= length2
;
229 data
[0] = this->command_prev
;
232 return length
+ repeat
;
235 int midibuf_ignore(struct MidiBuffer
*this, int length
)
237 int bytes_used
= midibuf_bytes_used(this);
239 if (length
> bytes_used
)
242 this->pos_read
= (this->pos_read
+ length
) % this->size
;
247 int midibuf_skip_message(struct MidiBuffer
*this, unsigned short mask
)
249 int cmd
= this->command_prev
;
251 if ((cmd
>= 0x80) && (cmd
< 0xf0))
252 if ((mask
& (1 << (cmd
& 0x0f))) == 0)
258 void midibuf_destroy(struct MidiBuffer
*this)