Skip to content

Commit 00a7bb8

Browse files
takaswietiwai
authored andcommitted
ALSA: firewire-lib: Add support for deferred transaction
Some devices based on BeBoB use this type of AV/C transaction. 'Deferred Transaction' is defined in 'AV/C Digital Interface Command Set General Specification' and is used by targets to make a response deferred during processing it. If a target may not be able to complete a command within 100msec since receiving the command, then the target shall return INTERIM response, to which final response will follow later. CONTROL/NOTIFY commands are allowed for deferred transaction. In the specification, devices allow to send INTERIM response just one time. But this commit allows to handle several INTERIM response with two reasons. One reason is to simplify codes, and another reason is to prepare for devices which is out of specification. There is an issue. In the specification, the interval between INTERIM response and final response is 'Unspecified interval'. The specification depends on each subunit specification for this interval. But we promise to finish this function for caller. In this reason, I use FCP_TIMEOUT_MS for this interval. Currently it's 125msec. When we find devices which needs more time for this interval, then let us add some codes to apply more interval for 'Unspecified interval'. Signed-off-by: Takashi Sakamoto <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent b04479f commit 00a7bb8

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

sound/firewire/fcp.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum fcp_state {
3030
STATE_PENDING,
3131
STATE_BUS_RESET,
3232
STATE_COMPLETE,
33+
STATE_DEFERRED,
3334
};
3435

3536
struct fcp_transaction {
@@ -40,6 +41,7 @@ struct fcp_transaction {
4041
unsigned int response_match_bytes;
4142
enum fcp_state state;
4243
wait_queue_head_t wait;
44+
bool deferrable;
4345
};
4446

4547
/**
@@ -81,6 +83,9 @@ int fcp_avc_transaction(struct fw_unit *unit,
8183
t.state = STATE_PENDING;
8284
init_waitqueue_head(&t.wait);
8385

86+
if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03)
87+
t.deferrable = true;
88+
8489
spin_lock_irq(&transactions_lock);
8590
list_add_tail(&t.list, &transactions);
8691
spin_unlock_irq(&transactions_lock);
@@ -93,11 +98,21 @@ int fcp_avc_transaction(struct fw_unit *unit,
9398
(void *)command, command_size, 0);
9499
if (ret < 0)
95100
break;
96-
101+
deferred:
97102
wait_event_timeout(t.wait, t.state != STATE_PENDING,
98103
msecs_to_jiffies(FCP_TIMEOUT_MS));
99104

100-
if (t.state == STATE_COMPLETE) {
105+
if (t.state == STATE_DEFERRED) {
106+
/*
107+
* 'AV/C General Specification' define no time limit
108+
* on command completion once an INTERIM response has
109+
* been sent. but we promise to finish this function
110+
* for a caller. Here we use FCP_TIMEOUT_MS for next
111+
* interval. This is not in the specification.
112+
*/
113+
t.state = STATE_PENDING;
114+
goto deferred;
115+
} else if (t.state == STATE_COMPLETE) {
101116
ret = t.response_size;
102117
break;
103118
} else if (t.state == STATE_BUS_RESET) {
@@ -132,7 +147,8 @@ void fcp_bus_reset(struct fw_unit *unit)
132147
spin_lock_irq(&transactions_lock);
133148
list_for_each_entry(t, &transactions, list) {
134149
if (t->unit == unit &&
135-
t->state == STATE_PENDING) {
150+
(t->state == STATE_PENDING ||
151+
t->state == STATE_DEFERRED)) {
136152
t->state = STATE_BUS_RESET;
137153
wake_up(&t->wait);
138154
}
@@ -186,10 +202,15 @@ static void fcp_response(struct fw_card *card, struct fw_request *request,
186202

187203
if (t->state == STATE_PENDING &&
188204
is_matching_response(t, data, length)) {
189-
t->state = STATE_COMPLETE;
190-
t->response_size = min((unsigned int)length,
191-
t->response_size);
192-
memcpy(t->response_buffer, data, t->response_size);
205+
if (t->deferrable && *(const u8 *)data == 0x0f) {
206+
t->state = STATE_DEFERRED;
207+
} else {
208+
t->state = STATE_COMPLETE;
209+
t->response_size = min_t(unsigned int, length,
210+
t->response_size);
211+
memcpy(t->response_buffer, data,
212+
t->response_size);
213+
}
193214
wake_up(&t->wait);
194215
}
195216
}

0 commit comments

Comments
 (0)