diff options
-rw-r--r-- | drivers/bluetooth/hci_h5.c | 230 |
1 files changed, 222 insertions, 8 deletions
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index ae1bd32d8ef9..ddf7ebbaaef3 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c | |||
@@ -34,20 +34,37 @@ | |||
34 | 34 | ||
35 | #define H5_ACK_TIMEOUT msecs_to_jiffies(250) | 35 | #define H5_ACK_TIMEOUT msecs_to_jiffies(250) |
36 | 36 | ||
37 | /* | ||
38 | * Maximum Three-wire packet: | ||
39 | * 4 byte header + max value for 12-bit length + 2 bytes for CRC | ||
40 | */ | ||
41 | #define H5_MAX_LEN (4 + 0xfff + 2) | ||
42 | |||
43 | #define SLIP_DELIMITER 0xc0 | ||
44 | #define SLIP_ESC 0xdb | ||
45 | #define SLIP_ESC_DELIM 0xdc | ||
46 | #define SLIP_ESC_ESC 0xdd | ||
47 | |||
37 | struct h5 { | 48 | struct h5 { |
38 | struct sk_buff_head unack; /* Unack'ed packets queue */ | 49 | struct sk_buff_head unack; /* Unack'ed packets queue */ |
39 | struct sk_buff_head rel; /* Reliable packets queue */ | 50 | struct sk_buff_head rel; /* Reliable packets queue */ |
40 | struct sk_buff_head unrel; /* Unreliable packets queue */ | 51 | struct sk_buff_head unrel; /* Unreliable packets queue */ |
41 | 52 | ||
42 | struct sk_buff *rx_skb; | 53 | struct sk_buff *rx_skb; /* Receive buffer */ |
54 | size_t rx_pending; /* Expecting more bytes */ | ||
55 | bool rx_esc; /* SLIP escape mode */ | ||
43 | 56 | ||
44 | struct timer_list timer; /* Retransmission timer */ | 57 | int (*rx_func) (struct hci_uart *hu, u8 c); |
45 | 58 | ||
46 | bool txack_req; | 59 | struct timer_list timer; /* Retransmission timer */ |
47 | 60 | ||
48 | u8 msgq_txseq; | 61 | bool txack_req; |
62 | |||
63 | u8 msgq_txseq; | ||
49 | }; | 64 | }; |
50 | 65 | ||
66 | static void h5_reset_rx(struct h5 *h5); | ||
67 | |||
51 | static void h5_timed_event(unsigned long arg) | 68 | static void h5_timed_event(unsigned long arg) |
52 | { | 69 | { |
53 | struct hci_uart *hu = (struct hci_uart *) arg; | 70 | struct hci_uart *hu = (struct hci_uart *) arg; |
@@ -85,6 +102,8 @@ static int h5_open(struct hci_uart *hu) | |||
85 | skb_queue_head_init(&h5->rel); | 102 | skb_queue_head_init(&h5->rel); |
86 | skb_queue_head_init(&h5->unrel); | 103 | skb_queue_head_init(&h5->unrel); |
87 | 104 | ||
105 | h5_reset_rx(h5); | ||
106 | |||
88 | init_timer(&h5->timer); | 107 | init_timer(&h5->timer); |
89 | h5->timer.function = h5_timed_event; | 108 | h5->timer.function = h5_timed_event; |
90 | h5->timer.data = (unsigned long) hu; | 109 | h5->timer.data = (unsigned long) hu; |
@@ -107,9 +126,204 @@ static int h5_close(struct hci_uart *hu) | |||
107 | return 0; | 126 | return 0; |
108 | } | 127 | } |
109 | 128 | ||
129 | static void h5_handle_internal_rx(struct hci_uart *hu) | ||
130 | { | ||
131 | BT_DBG("%s", hu->hdev->name); | ||
132 | } | ||
133 | |||
134 | static void h5_complete_rx_pkt(struct hci_uart *hu) | ||
135 | { | ||
136 | struct h5 *h5 = hu->priv; | ||
137 | u8 pkt_type; | ||
138 | |||
139 | BT_DBG("%s", hu->hdev->name); | ||
140 | |||
141 | pkt_type = h5->rx_skb->data[1] & 0x0f; | ||
142 | |||
143 | switch (pkt_type) { | ||
144 | case HCI_EVENT_PKT: | ||
145 | case HCI_ACLDATA_PKT: | ||
146 | case HCI_SCODATA_PKT: | ||
147 | bt_cb(h5->rx_skb)->pkt_type = pkt_type; | ||
148 | |||
149 | /* Remove Three-wire header */ | ||
150 | skb_pull(h5->rx_skb, 4); | ||
151 | |||
152 | hci_recv_frame(h5->rx_skb); | ||
153 | h5->rx_skb = NULL; | ||
154 | |||
155 | break; | ||
156 | |||
157 | default: | ||
158 | h5_handle_internal_rx(hu); | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | h5_reset_rx(h5); | ||
163 | } | ||
164 | |||
165 | static int h5_rx_crc(struct hci_uart *hu, unsigned char c) | ||
166 | { | ||
167 | struct h5 *h5 = hu->priv; | ||
168 | |||
169 | BT_DBG("%s 0x%02hhx", hu->hdev->name, c); | ||
170 | |||
171 | h5_complete_rx_pkt(hu); | ||
172 | h5_reset_rx(h5); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int h5_rx_payload(struct hci_uart *hu, unsigned char c) | ||
178 | { | ||
179 | struct h5 *h5 = hu->priv; | ||
180 | const unsigned char *hdr = h5->rx_skb->data; | ||
181 | |||
182 | BT_DBG("%s 0x%02hhx", hu->hdev->name, c); | ||
183 | |||
184 | if ((hdr[0] >> 4) & 0x01) { | ||
185 | h5->rx_func = h5_rx_crc; | ||
186 | h5->rx_pending = 2; | ||
187 | } else { | ||
188 | h5_complete_rx_pkt(hu); | ||
189 | h5_reset_rx(h5); | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c) | ||
196 | { | ||
197 | struct h5 *h5 = hu->priv; | ||
198 | const unsigned char *hdr = h5->rx_skb->data; | ||
199 | |||
200 | BT_DBG("%s 0x%02hhx", hu->hdev->name, c); | ||
201 | |||
202 | if (((hdr[0] + hdr[1] + hdr[2] + hdr[3]) & 0xff) != 0xff) { | ||
203 | BT_ERR("Invalid header checksum"); | ||
204 | h5_reset_rx(h5); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | h5->rx_func = h5_rx_payload; | ||
209 | h5->rx_pending = ((hdr[1] >> 4) & 0xff) + (hdr[2] << 4); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c) | ||
215 | { | ||
216 | struct h5 *h5 = hu->priv; | ||
217 | |||
218 | BT_DBG("%s 0x%02hhx", hu->hdev->name, c); | ||
219 | |||
220 | if (c == SLIP_DELIMITER) | ||
221 | return 1; | ||
222 | |||
223 | h5->rx_func = h5_rx_3wire_hdr; | ||
224 | h5->rx_pending = 4; | ||
225 | |||
226 | h5->rx_skb = bt_skb_alloc(H5_MAX_LEN, GFP_ATOMIC); | ||
227 | if (!h5->rx_skb) { | ||
228 | BT_ERR("Can't allocate mem for new packet"); | ||
229 | h5_reset_rx(h5); | ||
230 | return -ENOMEM; | ||
231 | } | ||
232 | |||
233 | h5->rx_skb->dev = (void *) hu->hdev; | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int h5_rx_delimiter(struct hci_uart *hu, unsigned char c) | ||
239 | { | ||
240 | struct h5 *h5 = hu->priv; | ||
241 | |||
242 | BT_DBG("%s 0x%02hhx", hu->hdev->name, c); | ||
243 | |||
244 | if (c == SLIP_DELIMITER) | ||
245 | h5->rx_func = h5_rx_pkt_start; | ||
246 | |||
247 | return 1; | ||
248 | } | ||
249 | |||
250 | static void h5_unslip_one_byte(struct h5 *h5, unsigned char c) | ||
251 | { | ||
252 | const u8 delim = SLIP_DELIMITER, esc = SLIP_ESC; | ||
253 | const u8 *byte = &c; | ||
254 | |||
255 | if (!h5->rx_esc && c == SLIP_ESC) { | ||
256 | h5->rx_esc = true; | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | if (h5->rx_esc) { | ||
261 | switch (c) { | ||
262 | case SLIP_ESC_DELIM: | ||
263 | byte = &delim; | ||
264 | break; | ||
265 | case SLIP_ESC_ESC: | ||
266 | byte = &esc; | ||
267 | break; | ||
268 | default: | ||
269 | BT_ERR("Invalid esc byte 0x%02hhx", c); | ||
270 | h5_reset_rx(h5); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | h5->rx_esc = false; | ||
275 | } | ||
276 | |||
277 | memcpy(skb_put(h5->rx_skb, 1), byte, 1); | ||
278 | h5->rx_pending--; | ||
279 | |||
280 | BT_DBG("unsliped 0x%02hhx", *byte); | ||
281 | } | ||
282 | |||
283 | static void h5_reset_rx(struct h5 *h5) | ||
284 | { | ||
285 | if (h5->rx_skb) { | ||
286 | kfree_skb(h5->rx_skb); | ||
287 | h5->rx_skb = NULL; | ||
288 | } | ||
289 | |||
290 | h5->rx_func = h5_rx_delimiter; | ||
291 | h5->rx_pending = 0; | ||
292 | h5->rx_esc = false; | ||
293 | } | ||
294 | |||
110 | static int h5_recv(struct hci_uart *hu, void *data, int count) | 295 | static int h5_recv(struct hci_uart *hu, void *data, int count) |
111 | { | 296 | { |
112 | return -ENOSYS; | 297 | struct h5 *h5 = hu->priv; |
298 | unsigned char *ptr = data; | ||
299 | |||
300 | BT_DBG("%s count %d", hu->hdev->name, count); | ||
301 | |||
302 | while (count > 0) { | ||
303 | int processed; | ||
304 | |||
305 | if (h5->rx_pending > 0) { | ||
306 | if (*ptr == SLIP_DELIMITER) { | ||
307 | BT_ERR("Too short H5 packet"); | ||
308 | h5_reset_rx(h5); | ||
309 | continue; | ||
310 | } | ||
311 | |||
312 | h5_unslip_one_byte(h5, *ptr); | ||
313 | |||
314 | ptr++; count--; | ||
315 | continue; | ||
316 | } | ||
317 | |||
318 | processed = h5->rx_func(hu, *ptr); | ||
319 | if (processed < 0) | ||
320 | return processed; | ||
321 | |||
322 | ptr += processed; | ||
323 | count -= processed; | ||
324 | } | ||
325 | |||
326 | return 0; | ||
113 | } | 327 | } |
114 | 328 | ||
115 | static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) | 329 | static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) |