Commit | Line | Data |
---|---|---|
705ececd | 1 | /* |
e1a164d7 | 2 | * Line6 Linux USB driver - 0.9.1beta |
705ececd | 3 | * |
1027f476 | 4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) |
705ececd MG |
5 | * |
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. | |
9 | * | |
10 | */ | |
11 | ||
5a0e3ad6 TH |
12 | #include <linux/slab.h> |
13 | ||
1027f476 | 14 | #include "driver.h" |
705ececd MG |
15 | #include "dumprequest.h" |
16 | ||
705ececd MG |
17 | /* |
18 | Set "dump in progress" flag. | |
19 | */ | |
20 | void line6_dump_started(struct line6_dump_request *l6dr, int dest) | |
21 | { | |
22 | l6dr->in_progress = dest; | |
23 | } | |
24 | ||
25 | /* | |
26 | Invalidate current channel, i.e., set "dump in progress" flag. | |
27 | Reading from the "dump" special file blocks until dump is completed. | |
28 | */ | |
29 | void line6_invalidate_current(struct line6_dump_request *l6dr) | |
30 | { | |
31 | line6_dump_started(l6dr, LINE6_DUMP_CURRENT); | |
32 | } | |
33 | ||
34 | /* | |
35 | Clear "dump in progress" flag and notify waiting processes. | |
36 | */ | |
37 | void line6_dump_finished(struct line6_dump_request *l6dr) | |
38 | { | |
39 | l6dr->in_progress = LINE6_DUMP_NONE; | |
1027f476 | 40 | wake_up(&l6dr->wait); |
705ececd MG |
41 | } |
42 | ||
43 | /* | |
44 | Send an asynchronous channel dump request. | |
45 | */ | |
766f9d20 | 46 | int line6_dump_request_async(struct line6_dump_request *l6dr, |
1027f476 | 47 | struct usb_line6 *line6, int num, int dest) |
705ececd MG |
48 | { |
49 | int ret; | |
1027f476 | 50 | line6_dump_started(l6dr, dest); |
766f9d20 GKH |
51 | ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer, |
52 | l6dr->reqbufs[num].length); | |
705ececd | 53 | |
766f9d20 | 54 | if (ret < 0) |
705ececd MG |
55 | line6_dump_finished(l6dr); |
56 | ||
57 | return ret; | |
58 | } | |
59 | ||
60 | /* | |
1027f476 | 61 | Wait for completion (interruptible). |
705ececd | 62 | */ |
1027f476 | 63 | int line6_dump_wait_interruptible(struct line6_dump_request *l6dr) |
705ececd | 64 | { |
e1a164d7 MG |
65 | return wait_event_interruptible(l6dr->wait, |
66 | l6dr->in_progress == LINE6_DUMP_NONE); | |
705ececd MG |
67 | } |
68 | ||
69 | /* | |
70 | Wait for completion. | |
71 | */ | |
1027f476 MG |
72 | void line6_dump_wait(struct line6_dump_request *l6dr) |
73 | { | |
74 | wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE); | |
75 | } | |
76 | ||
77 | /* | |
78 | Wait for completion (with timeout). | |
79 | */ | |
80 | int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout) | |
705ececd | 81 | { |
e1a164d7 MG |
82 | return wait_event_timeout(l6dr->wait, |
83 | l6dr->in_progress == LINE6_DUMP_NONE, | |
84 | timeout); | |
705ececd MG |
85 | } |
86 | ||
87 | /* | |
88 | Initialize dump request buffer. | |
89 | */ | |
766f9d20 GKH |
90 | int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf, |
91 | size_t len, int num) | |
705ececd | 92 | { |
94002c07 | 93 | l6dr->reqbufs[num].buffer = kmemdup(buf, len, GFP_KERNEL); |
766f9d20 GKH |
94 | if (l6dr->reqbufs[num].buffer == NULL) |
95 | return -ENOMEM; | |
705ececd MG |
96 | l6dr->reqbufs[num].length = len; |
97 | return 0; | |
98 | } | |
99 | ||
100 | /* | |
101 | Initialize dump request data structure (including one buffer). | |
102 | */ | |
766f9d20 GKH |
103 | int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf, |
104 | size_t len) | |
705ececd MG |
105 | { |
106 | int ret; | |
107 | ret = line6_dumpreq_initbuf(l6dr, buf, len, 0); | |
766f9d20 GKH |
108 | if (ret < 0) |
109 | return ret; | |
705ececd | 110 | init_waitqueue_head(&l6dr->wait); |
705ececd MG |
111 | return 0; |
112 | } | |
113 | ||
114 | /* | |
115 | Destruct dump request data structure. | |
116 | */ | |
117 | void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num) | |
118 | { | |
766f9d20 GKH |
119 | if (l6dr == NULL) |
120 | return; | |
121 | if (l6dr->reqbufs[num].buffer == NULL) | |
122 | return; | |
705ececd MG |
123 | kfree(l6dr->reqbufs[num].buffer); |
124 | l6dr->reqbufs[num].buffer = NULL; | |
125 | } | |
126 | ||
127 | /* | |
128 | Destruct dump request data structure. | |
129 | */ | |
130 | void line6_dumpreq_destruct(struct line6_dump_request *l6dr) | |
131 | { | |
766f9d20 GKH |
132 | if (l6dr->reqbufs[0].buffer == NULL) |
133 | return; | |
705ececd | 134 | line6_dumpreq_destructbuf(l6dr, 0); |
705ececd | 135 | } |