blob: 2a85a000607ca96bff753f16e91e9820320a2e5b [file] [log] [blame]
Dixon Petersond6a20a92012-09-27 15:58:50 -07001/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/slab.h>
14#include <linux/delay.h>
15#include <linux/diagchar.h>
16#include <linux/kmemleak.h>
17#include <linux/workqueue.h>
18#include "diagchar.h"
19#include "diagfwd_cntl.h"
20#include "diag_masks.h"
21
22int diag_event_config;
23int diag_event_num_bytes;
24
25#define ALL_EQUIP_ID 100
26#define ALL_SSID -1
27#define MAX_SSID_PER_RANGE 100
28
29struct mask_info {
30 int equip_id;
31 int num_items;
32 int index;
33};
34
35#define CREATE_MSG_MASK_TBL_ROW(XX) \
36do { \
37 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
38 msg_mask_tbl_ptr += 4; \
39 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
40 msg_mask_tbl_ptr += 4; \
41 /* mimic the last entry as actual_last while creation */ \
42 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
43 msg_mask_tbl_ptr += 4; \
44 /* increment by MAX_SSID_PER_RANGE cells */ \
45 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
46} while (0)
47
48#define WAIT_FOR_SMD(num_delays, delay_time) \
49do { \
50 int count; \
51 for (count = 0; count < (num_delays); count++) \
52 udelay((delay_time)); \
53} while (0)
54
55static void diag_print_mask_table(void)
56{
57/* Enable this to print mask table when updated */
58#ifdef MASK_DEBUG
59 int first, last, actual_last;
60 uint8_t *ptr = driver->msg_masks;
61 int i = 0;
62 pr_info("diag: F3 message mask table\n");
63 while (*(uint32_t *)(ptr + 4)) {
64 first = *(uint32_t *)ptr;
65 ptr += 4;
66 last = *(uint32_t *)ptr;
67 ptr += 4;
68 actual_last = *(uint32_t *)ptr;
69 ptr += 4;
70 pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
71 for (i = 0 ; i <= actual_last - first ; i++)
72 pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
73 ptr += MAX_SSID_PER_RANGE*4;
74 }
75#endif
76}
77
78void diag_create_msg_mask_table(void)
79{
80 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
81
82 CREATE_MSG_MASK_TBL_ROW(0);
83 CREATE_MSG_MASK_TBL_ROW(1);
84 CREATE_MSG_MASK_TBL_ROW(2);
85 CREATE_MSG_MASK_TBL_ROW(3);
86 CREATE_MSG_MASK_TBL_ROW(4);
87 CREATE_MSG_MASK_TBL_ROW(5);
88 CREATE_MSG_MASK_TBL_ROW(6);
89 CREATE_MSG_MASK_TBL_ROW(7);
90 CREATE_MSG_MASK_TBL_ROW(8);
91 CREATE_MSG_MASK_TBL_ROW(9);
92 CREATE_MSG_MASK_TBL_ROW(10);
93 CREATE_MSG_MASK_TBL_ROW(11);
94 CREATE_MSG_MASK_TBL_ROW(12);
95 CREATE_MSG_MASK_TBL_ROW(13);
96 CREATE_MSG_MASK_TBL_ROW(14);
97 CREATE_MSG_MASK_TBL_ROW(15);
98 CREATE_MSG_MASK_TBL_ROW(16);
99 CREATE_MSG_MASK_TBL_ROW(17);
100 CREATE_MSG_MASK_TBL_ROW(18);
101 CREATE_MSG_MASK_TBL_ROW(19);
102 CREATE_MSG_MASK_TBL_ROW(20);
103 CREATE_MSG_MASK_TBL_ROW(21);
104 CREATE_MSG_MASK_TBL_ROW(22);
105 CREATE_MSG_MASK_TBL_ROW(23);
106}
107
108static void diag_set_msg_mask(int rt_mask)
109{
110 int first_ssid, last_ssid, i;
111 uint8_t *parse_ptr, *ptr = driver->msg_masks;
112
113 mutex_lock(&driver->diagchar_mutex);
114 while (*(uint32_t *)(ptr + 4)) {
115 first_ssid = *(uint32_t *)ptr;
116 ptr += 8; /* increment by 8 to skip 'last' */
117 last_ssid = *(uint32_t *)ptr;
118 ptr += 4;
119 parse_ptr = ptr;
120 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
121 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
122 *(int *)parse_ptr = rt_mask;
123 parse_ptr += 4;
124 }
125 ptr += MAX_SSID_PER_RANGE * 4;
126 }
127 mutex_unlock(&driver->diagchar_mutex);
128}
129
130static void diag_update_msg_mask(int start, int end , uint8_t *buf)
131{
132 int found = 0, first, last, actual_last;
133 uint8_t *actual_last_ptr;
134 uint8_t *ptr = driver->msg_masks;
135 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
136 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
137
138 mutex_lock(&driver->diagchar_mutex);
139
140 /* First SSID can be zero : So check that last is non-zero */
141 while (*(uint32_t *)(ptr + 4)) {
142 first = *(uint32_t *)ptr;
143 ptr += 4;
144 last = *(uint32_t *)ptr;
145 ptr += 4;
146 actual_last = *(uint32_t *)ptr;
147 actual_last_ptr = ptr;
148 ptr += 4;
149 if (start >= first && start <= actual_last) {
150 ptr += (start - first)*4;
151 if (end > actual_last) {
152 pr_info("diag: ssid range mismatch\n");
153 actual_last = end;
154 *(uint32_t *)(actual_last_ptr) = end;
155 }
156 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
157 (((end - start)+1)*4))) {
158 pr_debug("diag: update ssid start %d, end %d\n",
159 start, end);
160 memcpy(ptr, buf , ((end - start)+1)*4);
161 } else
162 pr_alert("diag: Not enough space MSG_MASK\n");
163 found = 1;
164 break;
165 } else {
166 ptr += MAX_SSID_PER_RANGE*4;
167 }
168 }
169 /* Entry was not found - add new table */
170 if (!found) {
171 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
172 8 + ((end - start) + 1)*4)) {
173 memcpy(ptr, &(start) , 4);
174 ptr += 4;
175 memcpy(ptr, &(end), 4);
176 ptr += 4;
177 memcpy(ptr, &(end), 4); /* create actual_last entry */
178 ptr += 4;
179 pr_debug("diag: adding NEW ssid start %d, end %d\n",
180 start, end);
181 memcpy(ptr, buf , ((end - start) + 1)*4);
182 } else
183 pr_alert("diag: Not enough buffer space for MSG_MASK\n");
184 }
185 mutex_unlock(&driver->diagchar_mutex);
186 diag_print_mask_table();
187}
188
189void diag_toggle_event_mask(int toggle)
190{
191 uint8_t *ptr = driver->event_masks;
192
193 mutex_lock(&driver->diagchar_mutex);
194 if (toggle)
195 memset(ptr, 0xFF, EVENT_MASK_SIZE);
196 else
197 memset(ptr, 0, EVENT_MASK_SIZE);
198 mutex_unlock(&driver->diagchar_mutex);
199}
200
201
202static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
203{
204 uint8_t *ptr = driver->event_masks;
205 uint8_t *temp = buf + 2;
206
207 mutex_lock(&driver->diagchar_mutex);
208 if (!toggle)
209 memset(ptr, 0 , EVENT_MASK_SIZE);
210 else
211 if (CHK_OVERFLOW(ptr, ptr,
212 ptr+EVENT_MASK_SIZE, num_bytes))
213 memcpy(ptr, temp , num_bytes);
214 else
215 printk(KERN_CRIT "Not enough buffer space for EVENT_MASK\n");
216 mutex_unlock(&driver->diagchar_mutex);
217}
218
219static void diag_disable_log_mask(void)
220{
221 int i = 0;
222 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
223
224 pr_debug("diag: disable log masks\n");
225 mutex_lock(&driver->diagchar_mutex);
226 for (i = 0; i < MAX_EQUIP_ID; i++) {
227 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
228 if (!(parse_ptr->equip_id)) /* Reached a null entry */
229 break;
230 memset(driver->log_masks + parse_ptr->index, 0,
231 (parse_ptr->num_items + 7)/8);
232 parse_ptr++;
233 }
234 mutex_unlock(&driver->diagchar_mutex);
235}
236
237int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
238{
239 int i = 0, flag = 0, num_items, offset;
240 unsigned char *ptr_data;
241 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
242
243 pr_debug("diag: received equip id = %d\n", equip_id);
244 /* Check if this is valid equipment ID */
245 for (i = 0; i < MAX_EQUIP_ID; i++) {
246 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
247 offset = ptr->index;
248 num_items = ptr->num_items;
249 flag = 1;
250 break;
251 }
252 ptr++;
253 }
254 if (!flag)
255 return -EPERM;
256 ptr_data = driver->log_masks + offset;
257 memcpy(buf, ptr_data, (num_items+7)/8);
258 return 0;
259}
260
261static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
262{
263 uint8_t *temp = buf;
264 int i = 0;
265 unsigned char *ptr_data;
266 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
267 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
268
269 pr_debug("diag: received equip id = %d\n", equip_id);
270 mutex_lock(&driver->diagchar_mutex);
271 /* Check if we already know index of this equipment ID */
272 for (i = 0; i < MAX_EQUIP_ID; i++) {
273 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
274 offset = ptr->index;
275 break;
276 }
277 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
278 /* Reached a null entry */
279 ptr->equip_id = equip_id;
280 ptr->num_items = num_items;
281 ptr->index = driver->log_masks_length;
282 offset = driver->log_masks_length;
283 driver->log_masks_length += ((num_items+7)/8);
284 break;
285 }
286 ptr++;
287 }
288 ptr_data = driver->log_masks + offset;
289 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
290 + LOG_MASK_SIZE, (num_items+7)/8))
291 memcpy(ptr_data, temp , (num_items+7)/8);
292 else
293 pr_err("diag: Not enough buffer space for LOG_MASK\n");
294 mutex_unlock(&driver->diagchar_mutex);
295}
296
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800297void diag_mask_update_fn(struct work_struct *work)
Dixon Petersond6a20a92012-09-27 15:58:50 -0700298{
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800299 struct diag_smd_info *smd_info = container_of(work,
300 struct diag_smd_info,
301 diag_notify_update_smd_work);
302 if (!smd_info) {
303 pr_err("diag: In %s, smd info is null, cannot update masks for the peripheral\n",
304 __func__);
305 return;
306 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700307
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800308 diag_send_msg_mask_update(smd_info->ch, ALL_SSID, ALL_SSID,
309 smd_info->peripheral);
310 diag_send_log_mask_update(smd_info->ch, ALL_EQUIP_ID);
311 diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
Dixon Petersond6a20a92012-09-27 15:58:50 -0700312
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800313 smd_info->notify_context = 0;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700314}
315
316void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
317{
318 void *buf = driver->buf_log_mask_update;
319 int header_size = sizeof(struct diag_ctrl_log_mask);
320 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
321 int i, size, wr_size = -ENOMEM, retry_count = 0;
322
323 mutex_lock(&driver->diag_cntl_mutex);
324 for (i = 0; i < MAX_EQUIP_ID; i++) {
325 size = (ptr->num_items+7)/8;
326 /* reached null entry */
327 if ((ptr->equip_id == 0) && (ptr->index == 0))
328 break;
329 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
330 driver->log_mask->num_items = ptr->num_items;
331 driver->log_mask->data_len = 11 + size;
332 driver->log_mask->stream_id = 1; /* 2, if dual stream */
333 driver->log_mask->status = 3; /* status for valid mask */
334 driver->log_mask->equip_id = ptr->equip_id;
335 driver->log_mask->log_mask_size = size;
336 /* send only desired update, NOT ALL */
337 if (equip_id == ALL_EQUIP_ID || equip_id ==
338 driver->log_mask->equip_id) {
339 memcpy(buf, driver->log_mask, header_size);
340 memcpy(buf+header_size, driver->log_masks+ptr->index,
341 size);
342 if (ch) {
343 while (retry_count < 3) {
344 wr_size = smd_write(ch, buf,
345 header_size + size);
346 if (wr_size == -ENOMEM) {
347 retry_count++;
348 WAIT_FOR_SMD(5, 2000);
349 } else
350 break;
351 }
352 if (wr_size != header_size + size)
353 pr_err("diag: log mask update failed %d, tried %d",
354 wr_size, header_size + size);
355 else
356 pr_debug("diag: updated log equip ID %d,len %d\n",
357 driver->log_mask->equip_id,
358 driver->log_mask->log_mask_size);
359 } else
360 pr_err("diag: ch not valid for log update\n");
361 }
362 ptr++;
363 }
364 mutex_unlock(&driver->diag_cntl_mutex);
365}
366
367void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
368{
369 void *buf = driver->buf_event_mask_update;
370 int header_size = sizeof(struct diag_ctrl_event_mask);
371 int wr_size = -ENOMEM, retry_count = 0;
372
373 mutex_lock(&driver->diag_cntl_mutex);
374 if (num_bytes == 0) {
375 pr_debug("diag: event mask not set yet, so no update\n");
376 mutex_unlock(&driver->diag_cntl_mutex);
377 return;
378 }
379 /* send event mask update */
380 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
381 driver->event_mask->data_len = 7 + num_bytes;
382 driver->event_mask->stream_id = 1; /* 2, if dual stream */
383 driver->event_mask->status = 3; /* status for valid mask */
384 driver->event_mask->event_config = diag_event_config; /* event config */
385 driver->event_mask->event_mask_size = num_bytes;
386 memcpy(buf, driver->event_mask, header_size);
387 memcpy(buf+header_size, driver->event_masks, num_bytes);
388 if (ch) {
389 while (retry_count < 3) {
390 wr_size = smd_write(ch, buf, header_size + num_bytes);
391 if (wr_size == -ENOMEM) {
392 retry_count++;
393 WAIT_FOR_SMD(5, 2000);
394 } else
395 break;
396 }
397 if (wr_size != header_size + num_bytes)
398 pr_err("diag: error writing event mask %d, tried %d\n",
399 wr_size, header_size + num_bytes);
400 } else
401 pr_err("diag: ch not valid for event update\n");
402 mutex_unlock(&driver->diag_cntl_mutex);
403}
404
405void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
406 int updated_ssid_last, int proc)
407{
408 void *buf = driver->buf_msg_mask_update;
409 int first, last, actual_last, size = -ENOMEM, retry_count = 0;
410 int header_size = sizeof(struct diag_ctrl_msg_mask);
411 uint8_t *ptr = driver->msg_masks;
412
413 mutex_lock(&driver->diag_cntl_mutex);
414 while (*(uint32_t *)(ptr + 4)) {
415 first = *(uint32_t *)ptr;
416 ptr += 4;
417 last = *(uint32_t *)ptr;
418 ptr += 4;
419 actual_last = *(uint32_t *)ptr;
420 ptr += 4;
421 if ((updated_ssid_first >= first && updated_ssid_last <=
422 actual_last) || (updated_ssid_first == ALL_SSID)) {
423 /* send f3 mask update */
424 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
425 driver->msg_mask->msg_mask_size = actual_last -
426 first + 1;
427 driver->msg_mask->data_len = 11 +
428 4 * (driver->msg_mask->msg_mask_size);
429 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
430 driver->msg_mask->status = 3; /* status valid mask */
431 driver->msg_mask->msg_mode = 0; /* Legcay mode */
432 driver->msg_mask->ssid_first = first;
433 driver->msg_mask->ssid_last = actual_last;
434 memcpy(buf, driver->msg_mask, header_size);
435 memcpy(buf+header_size, ptr,
436 4 * (driver->msg_mask->msg_mask_size));
437 if (ch) {
438 while (retry_count < 3) {
439 size = smd_write(ch, buf, header_size +
440 4*(driver->msg_mask->msg_mask_size));
441 if (size == -ENOMEM) {
442 retry_count++;
443 WAIT_FOR_SMD(5, 2000);
444 } else
445 break;
446 }
447 if (size != header_size +
448 4*(driver->msg_mask->msg_mask_size))
449 pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
450 proc, size, (header_size +
451 4*(driver->msg_mask->msg_mask_size)));
452 else
453 pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
454 first, actual_last, proc);
455 } else
456 pr_err("diag: proc %d, ch invalid msg mask update\n",
457 proc);
458 }
459 ptr += MAX_SSID_PER_RANGE*4;
460 }
461 mutex_unlock(&driver->diag_cntl_mutex);
462}
463
464int diag_process_apps_masks(unsigned char *buf, int len)
465{
466 int packet_type = 1;
467 int i;
468 int ssid_first, ssid_last, ssid_range;
469 int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
470 uint8_t *rt_mask_ptr;
471 int equip_id, num_items;
472#if defined(CONFIG_DIAG_OVER_USB)
473 int payload_length;
474#endif
475
476 /* Set log masks */
477 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
478 buf += 8;
479 /* Read Equip ID and pass as first param below*/
480 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
481 diag_update_userspace_clients(LOG_MASKS_TYPE);
482#if defined(CONFIG_DIAG_OVER_USB)
483 if (chk_apps_only()) {
484 driver->apps_rsp_buf[0] = 0x73;
485 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
486 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
487 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
488 for (i = 0; i < payload_length; i++)
489 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800490
491 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
492 if (driver->smd_cntl[i].ch)
493 diag_send_log_mask_update(
494 driver->smd_cntl[i].ch,
495 *(int *)buf);
496 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700497 encode_rsp_and_send(12 + payload_length - 1);
498 return 0;
499 }
500#endif
501 } /* Get log masks */
502 else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
503#if defined(CONFIG_DIAG_OVER_USB)
Dixon Petersoneecbadb2012-12-10 21:59:28 -0800504 if (!(driver->smd_data[MODEM_DATA].ch) &&
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800505 chk_apps_only()) {
Dixon Petersond6a20a92012-09-27 15:58:50 -0700506 equip_id = *(int *)(buf + 8);
507 num_items = *(int *)(buf + 12);
508 driver->apps_rsp_buf[0] = 0x73;
509 driver->apps_rsp_buf[1] = 0x0;
510 driver->apps_rsp_buf[2] = 0x0;
511 driver->apps_rsp_buf[3] = 0x0;
512 *(int *)(driver->apps_rsp_buf + 4) = 0x4;
513 if (!chk_equip_id_and_mask(equip_id,
514 driver->apps_rsp_buf+20))
515 *(int *)(driver->apps_rsp_buf + 8) = 0x0;
516 else
517 *(int *)(driver->apps_rsp_buf + 8) = 0x1;
518 *(int *)(driver->apps_rsp_buf + 12) = equip_id;
519 *(int *)(driver->apps_rsp_buf + 16) = num_items;
520 encode_rsp_and_send(20+(num_items+7)/8-1);
521 return 0;
522 }
523#endif
524 } /* Disable log masks */
525 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
526 /* Disable mask for each log code */
527 diag_disable_log_mask();
528 diag_update_userspace_clients(LOG_MASKS_TYPE);
529#if defined(CONFIG_DIAG_OVER_USB)
530 if (chk_apps_only()) {
531 driver->apps_rsp_buf[0] = 0x73;
532 driver->apps_rsp_buf[1] = 0x0;
533 driver->apps_rsp_buf[2] = 0x0;
534 driver->apps_rsp_buf[3] = 0x0;
535 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
536 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800537 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
538 if (driver->smd_cntl[i].ch)
539 diag_send_log_mask_update(
540 driver->smd_cntl[i].ch,
541 ALL_EQUIP_ID);
542
543 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700544 encode_rsp_and_send(11);
545 return 0;
546 }
547#endif
548 } /* Get runtime message mask */
549 else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
550 ssid_first = *(uint16_t *)(buf + 2);
551 ssid_last = *(uint16_t *)(buf + 4);
552#if defined(CONFIG_DIAG_OVER_USB)
Dixon Petersoneecbadb2012-12-10 21:59:28 -0800553 if (!(driver->smd_data[MODEM_DATA].ch) &&
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800554 chk_apps_only()) {
Dixon Petersond6a20a92012-09-27 15:58:50 -0700555 driver->apps_rsp_buf[0] = 0x7d;
556 driver->apps_rsp_buf[1] = 0x3;
557 *(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
558 *(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
559 driver->apps_rsp_buf[6] = 0x1; /* Success Status */
560 driver->apps_rsp_buf[7] = 0x0;
561 rt_mask_ptr = driver->msg_masks;
562 while (*(uint32_t *)(rt_mask_ptr + 4)) {
563 rt_first_ssid = *(uint32_t *)rt_mask_ptr;
564 rt_mask_ptr += 8; /* +8 to skip 'last' */
565 rt_last_ssid = *(uint32_t *)rt_mask_ptr;
566 rt_mask_ptr += 4;
567 if (ssid_first == rt_first_ssid && ssid_last ==
568 rt_last_ssid) {
569 rt_mask_size = 4 * (rt_last_ssid -
570 rt_first_ssid + 1);
571 memcpy(driver->apps_rsp_buf+8,
572 rt_mask_ptr, rt_mask_size);
573 encode_rsp_and_send(8+rt_mask_size-1);
574 return 0;
575 }
576 rt_mask_ptr += MAX_SSID_PER_RANGE*4;
577 }
578 }
579#endif
580 } /* Set runtime message mask */
581 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
582 ssid_first = *(uint16_t *)(buf + 2);
583 ssid_last = *(uint16_t *)(buf + 4);
584 ssid_range = 4 * (ssid_last - ssid_first + 1);
585 pr_debug("diag: received mask update for ssid_first = %d, ssid_last = %d",
586 ssid_first, ssid_last);
587 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
588 diag_update_userspace_clients(MSG_MASKS_TYPE);
589#if defined(CONFIG_DIAG_OVER_USB)
590 if (chk_apps_only()) {
591 for (i = 0; i < 8 + ssid_range; i++)
592 *(driver->apps_rsp_buf + i) = *(buf+i);
593 *(driver->apps_rsp_buf + 6) = 0x1;
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800594 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
595 if (driver->smd_cntl[i].ch)
596 diag_send_msg_mask_update(
597 driver->smd_cntl[i].ch,
598 ssid_first, ssid_last,
599 driver->smd_cntl[i].peripheral);
600
601 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700602 encode_rsp_and_send(8 + ssid_range - 1);
603 return 0;
604 }
605#endif
606 } /* Set ALL runtime message mask */
607 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
608 rt_mask = *(int *)(buf + 4);
609 diag_set_msg_mask(rt_mask);
610 diag_update_userspace_clients(MSG_MASKS_TYPE);
611#if defined(CONFIG_DIAG_OVER_USB)
612 if (chk_apps_only()) {
613 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
614 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
615 driver->apps_rsp_buf[2] = 1; /* success */
616 driver->apps_rsp_buf[3] = 0; /* rsvd */
617 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
618 /* send msg mask update to peripheral */
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800619 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
620 if (driver->smd_cntl[i].ch)
621 diag_send_msg_mask_update(
622 driver->smd_cntl[i].ch,
623 ALL_SSID, ALL_SSID,
624 driver->smd_cntl[i].peripheral);
625
626 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700627 encode_rsp_and_send(7);
628 return 0;
629 }
630#endif
631 } else if (*buf == 0x82) { /* event mask change */
632 buf += 4;
633 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
634 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
635 diag_update_userspace_clients(EVENT_MASKS_TYPE);
636#if defined(CONFIG_DIAG_OVER_USB)
637 if (chk_apps_only()) {
638 driver->apps_rsp_buf[0] = 0x82;
639 driver->apps_rsp_buf[1] = 0x0;
640 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
641 *(uint16_t *)(driver->apps_rsp_buf + 4) =
642 EVENT_LAST_ID + 1;
643 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
644 EVENT_LAST_ID/8+1);
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800645 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
646 if (driver->smd_cntl[i].ch)
647 diag_send_event_mask_update(
648 driver->smd_cntl[i].ch,
649 diag_event_num_bytes);
650 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700651 encode_rsp_and_send(6 + EVENT_LAST_ID/8);
652 return 0;
653 }
654#endif
655 } else if (*buf == 0x60) {
656 diag_event_config = *(buf+1);
657 diag_toggle_event_mask(*(buf+1));
658 diag_update_userspace_clients(EVENT_MASKS_TYPE);
659#if defined(CONFIG_DIAG_OVER_USB)
660 if (chk_apps_only()) {
661 driver->apps_rsp_buf[0] = 0x60;
662 driver->apps_rsp_buf[1] = 0x0;
663 driver->apps_rsp_buf[2] = 0x0;
Dixon Peterson66fb11b2012-12-04 20:30:54 -0800664 for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
665 if (driver->smd_cntl[i].ch)
666 diag_send_event_mask_update(
667 driver->smd_cntl[i].ch,
668 diag_event_num_bytes);
669 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700670 encode_rsp_and_send(2);
671 return 0;
672 }
673#endif
674 }
675
676 return packet_type;
677}
678
679void diag_masks_init(void)
680{
681 if (driver->event_mask == NULL) {
682 driver->event_mask = kzalloc(sizeof(
683 struct diag_ctrl_event_mask), GFP_KERNEL);
684 if (driver->event_mask == NULL)
685 goto err;
686 kmemleak_not_leak(driver->event_mask);
687 }
688 if (driver->msg_mask == NULL) {
689 driver->msg_mask = kzalloc(sizeof(
690 struct diag_ctrl_msg_mask), GFP_KERNEL);
691 if (driver->msg_mask == NULL)
692 goto err;
693 kmemleak_not_leak(driver->msg_mask);
694 }
695 if (driver->log_mask == NULL) {
696 driver->log_mask = kzalloc(sizeof(
697 struct diag_ctrl_log_mask), GFP_KERNEL);
698 if (driver->log_mask == NULL)
699 goto err;
700 kmemleak_not_leak(driver->log_mask);
701 }
702
703 if (driver->buf_msg_mask_update == NULL) {
704 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
705 GFP_KERNEL);
706 if (driver->buf_msg_mask_update == NULL)
707 goto err;
708 kmemleak_not_leak(driver->buf_msg_mask_update);
709 }
710 if (driver->buf_log_mask_update == NULL) {
711 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
712 GFP_KERNEL);
713 if (driver->buf_log_mask_update == NULL)
714 goto err;
715 kmemleak_not_leak(driver->buf_log_mask_update);
716 }
717 if (driver->buf_event_mask_update == NULL) {
718 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
719 GFP_KERNEL);
720 if (driver->buf_event_mask_update == NULL)
721 goto err;
722 kmemleak_not_leak(driver->buf_event_mask_update);
723 }
724 if (driver->msg_masks == NULL) {
725 driver->msg_masks = kzalloc(MSG_MASK_SIZE, GFP_KERNEL);
726 if (driver->msg_masks == NULL)
727 goto err;
728 kmemleak_not_leak(driver->msg_masks);
729 }
730 diag_create_msg_mask_table();
731 diag_event_num_bytes = 0;
732 if (driver->log_masks == NULL) {
733 driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL);
734 if (driver->log_masks == NULL)
735 goto err;
736 kmemleak_not_leak(driver->log_masks);
737 }
738 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
739 if (driver->event_masks == NULL) {
740 driver->event_masks = kzalloc(EVENT_MASK_SIZE, GFP_KERNEL);
741 if (driver->event_masks == NULL)
742 goto err;
743 kmemleak_not_leak(driver->event_masks);
744 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700745 return;
746err:
747 pr_err("diag: Could not initialize diag mask buffers");
748 kfree(driver->event_mask);
749 kfree(driver->log_mask);
750 kfree(driver->msg_mask);
751 kfree(driver->msg_masks);
752 kfree(driver->log_masks);
753 kfree(driver->event_masks);
754}
755
756void diag_masks_exit(void)
757{
758 kfree(driver->event_mask);
759 kfree(driver->log_mask);
760 kfree(driver->msg_mask);
761 kfree(driver->msg_masks);
762 kfree(driver->log_masks);
763 kfree(driver->event_masks);
764}