1/*
2 * This is a reverse-engineered driver for mobile WiMAX (802.16e) devices
3 * based on GCT Semiconductor GDM7213 & GDM7205 chip.
4 * Copyright (�) 2010 Yaroslav Levandovsky <leyarx@gmail.com>
5 *
6 * Based on  madWiMAX driver writed by Alexander Gordeev
7 * Copyright (C) 2008-2009 Alexander Gordeev <lasaine@lvk.cs.msu.su>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <string.h>
25#include <ctype.h>
26#include "logging.h"
27#include "protocol.h"
28#include "eap_auth.h"
29
30static int process_normal_config_response(struct wimax_dev_status *dev, const unsigned char *buf, int len)
31{
32	if (len > 4){
33		int i, j;
34		short param_len;
35		for (i = 0x04;i < len; )
36		{
37			param_len = buf[i+1];
38			switch (buf[i]){
39				case 0x00: {	//	-- Device MAC
40						if (param_len == 0x6) {
41							memcpy(dev->mac, buf + i + 2, param_len);
42							dev->info_updated |= WDS_MAC;
43						} else  wmlog_msg(1, "bad param_len");
44						break;
45					}
46				case 0x01: {	//	-- BSID
47						if (param_len == 0x6) {
48							memcpy(dev->bsid, buf + i + 2, param_len);
49							dev->info_updated |= WDS_BSID;
50						} else  wmlog_msg(1, "bad param_len");
51						break;
52					}
53				case 0x1b: {	//	-- Device SW Version  xxxx: (FW FirmWare)
54							for (j = i+2; j < param_len + i + 2; j++)
55							{
56								dev->firmware[j - (i + 2)] = buf[j] + 0x30; /* rewrite this part to use itoa() */
57							}
58							dev->firmware[0x04] = 0x3a;
59							//dev->info_updated |= WDS_FIRMWARE;  // -test
60							break;
61
62					}
63				case 0x1d: {	//	-- Device SW Version :xxxx
64							for (j = i+2; j < param_len + i + 2; j++)
65							{
66								dev->firmware[j - (i + 2) + 5] = buf[j] + 0x30; /* rewrite this part to use itoa() */
67							}
68							//memcpy(dev->firmware + 0x05, buf + i + 2, param_len);
69							dev->info_updated |= WDS_FIRMWARE;
70							break;
71					}
72				case 0x1f: {	//	-- Device HW Version (RF Version)
73							for (j = i+2; j < param_len + i + 2; j++)
74							{
75								dev->chip[j - (i + 2)] = buf[j] + 0x30; /* rewrite this part to use itoa() */
76							}
77							//memcpy(dev->chip, buf + i + 2, param_len);
78							dev->info_updated |= WDS_CHIP;
79							break;
80					}
81				case 0x60: {	//	-- RSSI-1
82							dev->rssi1 =  buf[i+0x2]-0x100;
83							dev->info_updated |= WDS_RSSI1;
84							break;
85					}
86				case 0x71: {	//	-- RSSI-2
87							dev->rssi2 =  buf[i+0x2]-0x100;
88							dev->info_updated |= WDS_RSSI2;
89							break;
90					}
91				case 0x61: {	//	-- CINR-1
92							dev->cinr1 =  buf[i+0x2];
93							dev->info_updated |= WDS_CINR1;
94							break;
95					}
96				case 0x72: {	//	-- CINR-2
97							dev->cinr2 =  buf[i+0x2];
98							dev->info_updated |= WDS_CINR2;
99							break;
100					}
101				case 0x6a: {	//	-- Tx - Power
102							dev->txpwr =  buf[i+0x2] / 2;
103							dev->info_updated |= WDS_TXPWR;
104							break;
105					}
106				case 0x7f: {	//	-- Frequency
107							dev->freq = (buf[i+0x2] << 24) + (buf[i+0x3] << 16) + (buf[i+0x4] << 8) + buf[i+0x5];
108							dev->info_updated |= WDS_FREQ;
109							break;
110					}
111		        case 0xd1: {	//	-- Home Network data from device
112						break;
113					}
114		        case 0xd2: {	//	--  H-NSP ID
115						if (param_len == 0x3) {
116							dev->nspid=(buf[i + 2]<<16) + (buf[i + 3]<<8) + buf[i + 4];
117							dev->info_updated |= WDS_NSPID;
118						} else
119							wmlog_msg(1, "bad param_len H-NSPID");
120						break;
121					}
122/*				case 0xd4:	//	-- Network name
123						memcpy(dev->netname, buf + i + 2, param_len);
124						dev->info_updated |= WDS_NETNAME;
125*/
126				default: {
127						wmlog_msg(3, "bad config format %02x",buf[i]);
128						break;
129						//return -1;
130					}
131			}
132			if (buf[i] == 0xd1)
133				i += 4;
134			else
135				i += buf[i+1] + 2;
136		}  // error if all param are unknown!!!
137		return 0;
138	}
139
140	dev->info_updated |= WDS_OTHER;
141
142	return 0;
143
144	/*
145	short type_a = (buf[0x14] << 8) + buf[0x15];
146	short type_b = (buf[0x16] << 8) + buf[0x17];
147	short param_len = (buf[0x18] << 8) + buf[0x19];
148
149	if (type_a == 0x8 && type_b == 0x2) {
150		if (param_len != 0x80) {
151			wmlog_msg(1, "bad param_len");
152			return -1;
153		}
154		memcpy(dev->chip, buf + 0x1a, 0x40);
155		memcpy(dev->firmware, buf + 0x5a, 0x40);
156		dev->info_updated |= WDS_CHIP | WDS_FIRMWARE;
157		return 0;
158	}
159	if (type_a == 0x3 && type_b == 0x2) {
160		if (param_len != 0x6) {
161			wmlog_msg(1, "bad param_len");
162			return -1;
163		}
164		memcpy(dev->mac, buf + 0x1a, 0x6);
165		dev->info_updated |= WDS_MAC;
166		return 0;
167	}
168	if (type_a == 0x1 && type_b == 0x2) {
169		if (param_len != 0x2) {
170			wmlog_msg(1, "bad param_len");
171			return -1;
172		}
173		set_link_status((buf[0x1a] << 8) + buf[0x1b]);
174		return 0;
175	}
176	if (type_a == 0x1 && type_b == 0x3) {
177		if (param_len != 0x4) {
178			wmlog_msg(1, "bad param_len");
179			return -1;
180		}
181		set_link_status(0);
182		return 0;
183	}
184	if (type_a == 0x1 && type_b == 0xa) {
185		if (param_len != 0x16) {
186			wmlog_msg(1, "bad param_len");
187			return -1;
188		}
189		dev->rssi = (buf[0x1a] << 8) + buf[0x1b];
190		dev->cinr = (float)((short)((buf[0x1c] << 8) + buf[0x1d])) / 8;
191		memcpy(dev->bsid, buf + 0x1e, 0x6);
192		dev->txpwr = (buf[0x26] << 8) + buf[0x27];
193		dev->freq = (buf[0x28] << 24) + (buf[0x29] << 16) + (buf[0x2a] << 8) + buf[0x2b];
194		dev->info_updated |= WDS_RSSI | WDS_CINR | WDS_BSID | WDS_TXPWR | WDS_FREQ;
195		return 0;
196	}
197	if (type_a == 0x1 && type_b == 0xc) {
198		if (param_len != 0x2) {
199			wmlog_msg(1, "bad param_len");
200			return -1;
201		}
202		set_state((buf[0x1a] << 8) + buf[0x1b]);
203		return 0;
204	}
205
206	dev->info_updated |= WDS_OTHER;
207
208	return 0;
209	*/
210}
211/*
212static int process_debug_config_response(struct wimax_dev_status *dev, const unsigned char *buf, int len)
213{
214	dev->info_updated |= WDS_OTHER;
215	return 0;
216}
217*/
218static int process_config_response(struct wimax_dev_status *dev, const unsigned char *buf, int len)
219{
220	/*
221	if (buf[0x12] != 0x15) {
222		wmlog_msg(1, "bad format");
223		return -1;
224	}
225*/
226	switch (buf[1]) {
227		case 0x03:
228			return process_normal_config_response(dev, buf, len);
229	/*	case 0x02:
230			return process_debug_config_response(dev, buf, len);
231		case 0x04:
232			break;*/
233		default: {
234				wmlog_msg(1, "bad format");
235				return -1;
236			}
237	}
238
239	dev->info_updated |= WDS_OTHER;
240
241	return 0;
242}
243
244static int process_E_response(struct wimax_dev_status *dev, const unsigned char *buf, int len)
245{
246	int i;
247	short param_len;
248
249	switch (buf[0x01]){
250		case 0x0f: {	//	-- find network
251				if (len == 0x04)
252					dev->link_status = 0;
253				else {
254					//int i;
255					//short param_len;
256					for (i = 0x04;i < len; i += buf[i+1] + 2)
257					{
258						//param_len = buf[i+1];
259						//if (buf[i] == 0xd6) memcpy(dev->napid, buf + i + 2, param_len);
260						if (buf[i] == 0xd6) dev->napid=(buf[i + 2]<<16) + (buf[i + 3]<<8) + buf[i + 4];
261						/*
262						if (buf[i] == 0x61 && i+14 < len){
263							if (buf[i+2] == buf[len-4] && buf[i+5] == buf[len-1])
264								memcpy(dev->bsid, buf + i + 8, 0x06);
265
266							i += 14;
267						}
268						*/
269					}
270					dev->link_status = 1;
271				}
272				dev->info_updated |= WDS_LINK_STATUS;
273				return 0;
274				//break;
275			}
276
277		case 0x12: {	//	--  Connection error
278
279				dev->auth_info = buf[0x04];
280
281				if (buf[0x04] == 0x00){
282
283					return 0;
284				}
285				//if (buf[len-1] == 0xff)
286				else {
287					dev->link_status = 0;
288					dev->info_updated |= WDS_LINK_STATUS;
289					return 0;
290				}
291
292				//break;
293			}
294		case 0x13: {	//	--  Connecting to BS;
295				for (i = 0x04;i < len; i += buf[i+1] + 2)
296				{
297					param_len = buf[i+1];
298					if (buf[i] == 0x01) {
299						memcpy(dev->bsid, buf + i + 2, 0x06);
300						wmlog_msg(0, "Connecting to BSID: %02x:%02x:%02x:%02x:%02x:%02x", dev->bsid[0], dev->bsid[1], dev->bsid[2], dev->bsid[3], dev->bsid[4], dev->bsid[5]);
301					}
302				}
303				dev->link_status = 1;
304				dev->info_updated |= WDS_LINK_STATUS;
305				return 0;
306				//break;
307			}
308		case 0x14: {	//	--  Connecting to state;
309				if(buf[0x04] == 0x00) {
310					wmlog_msg(0, "Connected to BSID: %02x:%02x:%02x:%02x:%02x:%02x", dev->bsid[0], dev->bsid[1], dev->bsid[2], dev->bsid[3], dev->bsid[4], dev->bsid[5]);
311					dev->link_status = 1;
312				} else {
313					wmlog_msg(0, "Error connecting to BSID: %02x:%02x:%02x:%02x:%02x:%02x", dev->bsid[0], dev->bsid[1], dev->bsid[2], dev->bsid[3], dev->bsid[4], dev->bsid[5]);
314					dev->link_status = 0;
315				}
316				dev->info_updated |= WDS_LINK_STATUS;
317				return 0;
318				//break;
319			}
320		case 0x15: {
321			if (buf[0x03] > 0){
322				switch (buf[0x04])
323				{
324					case 0x00: {
325						wmlog_msg(1, "Disconnected by BS");
326						break;
327					}
328					case 0x01: {
329						wmlog_msg(1, "Disconnected by User");
330						break;
331					}
332					case 0x03: {
333						wmlog_msg(1, "Disconnected no BS");
334						break;
335					}
336					default:
337						wmlog_msg(1, "Unknown: %02x %02x ... %02x",buf[0x00], buf[0x01], buf[0x04]);
338				}
339			}
340			else {
341				wmlog_msg(1, "Unknown: %02x %02x %02x %02x",buf[0x00], buf[0x01], buf[0x02], buf[0x03]);
342			}
343			return 0;
344			}
345		case 0x16: {	//	--  Auth state
346				if (len == 0x07) {
347					//memcpy(dev->auth_state,buf+4,0x03);
348					dev->auth_state = (buf[4]<<16) + (buf[5]<<8) + buf[6];
349							//dev->freq = (buf[i+0x2] << 24) + (buf[i+0x3] << 16) + (buf[i+0x4] << 8) + buf[i+0x5];
350					dev->info_updated |= WDS_AUTH_STATE;
351					if ( dev->auth_state == 0x0201ff)
352						dev->info_updated |= WDS_EAP;
353
354					//wmlog_msg(0, "Auth State: %02x %02x %02x",dev->auth_state[0],dev->auth_state[1],dev->auth_state[2]);
355				} else  wmlog_msg(1, "bad param_len");
356				return 0;
357			}
358
359		case 0x17: {	//	--    Changing BS
360			if (len == 5 && buf[4] == 0x01) {
361				wmlog_msg(0, "Changing BS");
362			} else  wmlog_msg(1, "bad format: %02x %02x -> %02x",buf[0], buf[1], buf[4]);
363			return 0;
364			}
365
366		case 0x18: {	//	--    BS Changed, new BSID
367			if (buf[4] == 0x00) {
368				for (i = 5;i < len; i += buf[i+1] + 2)
369				{
370					param_len = buf[i+1];
371					if (buf[i] == 0x01) {
372						memcpy(dev->bsid, buf + i + 2, 0x06);
373						wmlog_msg(0, "BSID Changed to: %02x:%02x:%02x:%02x:%02x:%02x", dev->bsid[0], dev->bsid[1], dev->bsid[2], dev->bsid[3], dev->bsid[4], dev->bsid[5]);
374					}
375				}
376			} else  wmlog_msg(1, "bad format: %02x %02x -> %02x",buf[0], buf[1], buf[4]);
377			return 0;
378			}
379
380		case 0x19: {	//	--  RF state
381				if (len == 0x05) {
382					dev->rf_state =  buf[len-1];
383					dev->info_updated |= WDS_RF_STATE;
384				} else  wmlog_msg(1, "bad param_len");
385				return 0;
386				//break;
387			}
388
389		default: {
390			wmlog_msg(3, "bad format: %02x %02x",buf[0], buf[1]);
391			return -1;
392			}
393	}
394/*
395
396	if (buf[0x5] == 0x3) {
397		dev->proto_flags = buf[0x7];
398		dev->info_updated |= WDS_PROTO_FLAGS;
399		return 0;
400	}
401*/
402	dev->info_updated |= WDS_OTHER;
403
404	return 0;
405}
406
407static int process_data_response(struct wimax_dev_status *dev, const unsigned char *buf, int len)
408{
409	switch (buf[0x01]){
410		case 0x01: {	//	-- EAP Authentification
411				eap_peer_rx(buf + 0x04, len - 0x04);
412				dev->info_updated |= WDS_EAP;
413			}
414		case 0x03:{ 	//	-- Ethernet frame
415				write_netif(buf + 0x04, len - 0x04);
416				return 0;
417			}
418		default: {
419				wmlog_msg(1, "bad format: %02x %02x",buf[0], buf[1]);
420				return -1;
421			}
422	}
423	return 0;
424}
425
426static int process_P_response(struct wimax_dev_status *dev, const unsigned char *buf, int len) //83
427{
428	short param_len;
429
430	switch (buf[0x01]){
431		case 0x0d: {	//	-- Text out
432				int i;
433				//unsigned char data[buf[0x02]<<8+buf[0x03]+1];
434				unsigned char data[0x4000];
435				for (i = 4; i < len; i++)
436				{
437					if (isprint(buf[i])) {
438						data[i-4] = buf[i];
439					}
440					else {
441						if (buf[i] == 0x0a){
442							data[i-4] = 0x0a;
443						}
444						else {
445							data[i-4] = 0x20;
446						}
447					}
448				}
449				data[len-4] = 0x00; //��������� ����
450				wmlog_msg(2, "%s", data);
451				//memset(data,0,sizeof(data));
452				//dev->info_updated |= WDS_OTHER;
453				break;
454			}
455		case 0x11: {
456				short code;
457				int offset;
458				param_len = (buf[2] << 8) + buf[3] - 6;
459				code = (buf[4] << 8) + buf[5];
460				offset = (buf[6] << 24) + (buf[7] << 16) + (buf[8] << 8) + buf[9];
461				wmlog_msg(0, "Image DL code: %04x offset: %08x len: %04x", code, offset, param_len);
462				dev->info_updated |= WDS_CERT;
463				break;
464			}
465		case 0x13: {
466				param_len = (buf[2] << 8) + buf[3];
467				if (param_len == 6)
468				{
469					memcpy(dev->cert,buf+4,param_len);
470					if (buf[6] == 0xff && ((dev->cert_buf[0]<<8)+dev->cert_buf[1]) == 0)
471						wmlog_msg(1, "Cert %d is empty.",buf[5]);
472					if (buf[6] == 0xff)
473						wmlog_msg(2, "Reading cert %d finished.",buf[5]);
474					dev->info_updated |= WDS_CERT;
475					break;
476				}
477				if (param_len > 6)
478				{
479					if (buf[8] == 0x00)
480						wmlog_msg(2, "Start reading cert %d.",buf[5]);
481					memcpy(dev->cert,buf+4,6);
482					dev->cert_buf[0] = ((param_len-6) >> 8) & 0xff;
483					dev->cert_buf[1] = (param_len-6) & 0xff;
484					memcpy(dev->cert_buf+2,buf+10,param_len-6);
485					wmlog_msg(2, "Read %d bytes of cert %d.",param_len-6+(buf[8]<<8),buf[5]);
486					dev->info_updated |= WDS_CERT;
487					break;
488				}
489				wmlog_msg(2, "bad cert size %d",param_len);
490				dev->info_updated |= WDS_CERT;
491				break;
492			}
493		case 0x23: {
494				if(buf[0x04] == 0x07) {
495					dev->link_status = 0;
496					wmlog_msg(0, "Signal is Lost");
497					//dev->info_updated |= WDS_LINK_STATUS;
498					return 0;
499				} else {
500					wmlog_msg(1, "bad format: %02x %02x",buf[0], buf[1]);
501					return 0;
502				}
503			}
504		default: {
505			wmlog_msg(1, "bad format: %02x %02x",buf[0], buf[1]);
506			break;
507			}
508	}
509	dev->info_updated |= WDS_OTHER;
510	return 0;
511}
512
513int process_response(struct wimax_dev_status *dev, const unsigned char *buf, int len) //Ok
514{
515	int check_len;
516
517	if(len < 4) {
518		wmlog_msg(1, "short read");
519		return -1;
520	}
521/*
522	if(buf[0] != 0x57) {
523		wmlog_msg(1, "bad header");
524		return -1;
525	}
526*/
527	check_len = 4 + (buf[2] << 8) + buf[3];
528/*
529
530	if(buf[0] == 0x82 && buf[1] == 0x03) {
531		check_len += 3;
532	}
533
534
535	if(check_len != len) {
536		wmlog_msg(1, "bad length: %02x instead of %02x", check_len, len);
537		return -1;
538	}
539*/
540
541	if(check_len != len && check_len+1 != len && check_len+2 != len && check_len+3 != len) {
542		wmlog_msg(1, "bad length: %02x instead of %02x", check_len, len);
543		return -1;
544	}
545
546	switch (buf[0x00]) {
547		case 0x80:
548			return process_config_response(dev, buf, len);
549		case 0x81:
550			return process_E_response(dev, buf, len);
551		case 0x82:
552			return process_data_response(dev, buf, len);
553		case 0x83:
554			return process_P_response(dev, buf, len);
555		default: {
556			wmlog_msg(1, "bad response type: %02x", buf[0]);
557			return -1;
558			}
559	}
560}
561
562// static inline void fill_outgoing_packet_header(unsigned char *buf, unsigned char type, int body_len)
563static inline void fill_outgoing_packet_header(unsigned char *buf, unsigned short type_a, unsigned char type_b, int body_len) //Ok
564{
565	buf[0x00] = type_a;
566	buf[0x01] = type_b;
567	buf[0x02] = (body_len >> 8) & 0xff;
568	buf[0x03] = body_len & 0xff;
569}
570/*
571int fill_protocol_info_req(unsigned char *buf, unsigned char flags)
572{
573	fill_outgoing_packet_header(buf, 0x45, 4);
574	buf += HEADER_LENGTH_LOWLEVEL;
575	buf[0x00] = 0x00;
576	buf[0x01] = 0x02;
577	buf[0x02] = 0x00;
578	buf[0x03] = flags;
579	return HEADER_LENGTH_LOWLEVEL + 4;
580}
581
582int fill_mac_lowlevel_req(unsigned char *buf)
583{
584	fill_outgoing_packet_header(buf, 0x50, 0x14);
585	buf += HEADER_LENGTH_LOWLEVEL;
586	memset(buf, 0, 0x14);
587	buf[0x0c] = 0x15;
588	buf[0x0d] = 0x0a;
589	return HEADER_LENGTH_LOWLEVEL + 0x14;
590}
591*/
592/*
593static inline void fill_config_req(unsigned char *buf, int body_len)
594{
595	fill_outgoing_packet_header(buf, 0x00, 0x02, body_len);
596	//memset(buf + HEADER_LENGTH, 0, 12);
597}
598*/
599static int fill_normal_config_req(unsigned char *buf, unsigned short type_a, unsigned short type_b, unsigned short param_len, unsigned char *param) //Ok
600{
601	int body_len = param_len;
602	fill_outgoing_packet_header(buf, type_a, type_b, body_len);
603	//fill_config_req(buf, body_len);
604	/*
605	buf[0x04] = 0x15;
606	buf[0x05] = 0x00;
607	buf += HEADER_LENGTH;
608	buf[0x0c] = 0x15;
609	buf[0x0d] = 0x00;
610	buf[0x0e] = type_a >> 8;
611	buf[0x0f] = type_a & 0xff;
612	buf[0x10] = type_b >> 8;
613	buf[0x11] = type_b & 0xff;
614	buf[0x12] = param_len >> 8;
615	buf[0x13] = param_len & 0xff;
616	*/
617	memcpy(buf + 0x04, param, param_len);
618	return HEADER_LENGTH + body_len;
619}
620/*
621static int fill_normal_config_req(unsigned char *buf, unsigned short type_a, unsigned short type_b, unsigned short param_len, unsigned char *param)
622{
623	int body_len = 0x14 + param_len;
624	fill_config_req(buf, body_len);
625	buf[0x04] = 0x15;
626	buf[0x05] = 0x00;
627	buf += HEADER_LENGTH;
628	buf[0x0c] = 0x15;
629	buf[0x0d] = 0x00;
630	buf[0x0e] = type_a >> 8;
631	buf[0x0f] = type_a & 0xff;
632	buf[0x10] = type_b >> 8;
633	buf[0x11] = type_b & 0xff;
634	buf[0x12] = param_len >> 8;
635	buf[0x13] = param_len & 0xff;
636	memcpy(buf + 0x14, param, param_len);
637	return HEADER_LENGTH + body_len;
638}
639*/
640//>> -- Change Open Mode  00 = Normal 01 = Test (last byte)
641//00 01 00 03 b1 01 00
642int fill_init_cmd(unsigned char *buf) // Ok
643{
644	unsigned char param[] = {0xb1, 0x01, 0x00};
645	return fill_normal_config_req(buf, 0x00, 0x01, sizeof(param), param);
646	/*
647	fill_config_req(buf, 0x12);
648	buf[0x04] = 0x15;
649	buf[0x05] = 0x04;
650	buf += HEADER_LENGTH;
651	buf[0x0c] = 0x15;
652	buf[0x0d] = 0x04;
653	buf[0x0e] = 0x50;
654	buf[0x0f] = 0x04;
655	return HEADER_LENGTH + 0x12; */
656}
657
658int fill_auth_on_req(unsigned char *buf) // OK
659{
660	unsigned char param[] = {0xaf, 0x01, 0x01};
661	return fill_normal_config_req(buf, 0x00, 0x01, sizeof(param), param);
662}
663
664int fill_string_info_req(unsigned char *buf) // Ok
665{
666	unsigned char param[] = {0x1b, 0x1d, 0x1f};
667	return fill_normal_config_req(buf, 0x00, 0x02, sizeof(param), param);
668}
669
670int fill_get_nspid_req(unsigned char *buf) // Ok
671{
672	unsigned char param[] = {0xd1};
673	return fill_normal_config_req(buf, 0x00, 0x02, sizeof(param), param);
674}
675/*
676int fill_diode_control_cmd(unsigned char *buf, int turn_on)
677{
678	unsigned char param[0x2] = {0x0, turn_on ? 0x1 : 0x0};
679	return fill_normal_config_req(buf, 0x30, 0x1, sizeof(param), param);
680}
681*/
682
683int fill_mac_req(unsigned char *buf) // Ok
684{
685	unsigned char param[] = {0x00};
686	return fill_normal_config_req(buf, 0x00, 0x02, sizeof(param), param);
687}
688
689int fill_get_data_req_start(unsigned char *buf, short code)
690{
691	unsigned char param[6];
692	memset(param, 0, sizeof(param));
693	param[0] = (code >> 8) & 0xff;
694	param[1] = code & 0xff;
695	return fill_normal_config_req(buf, 0x03, 0x12, sizeof(param), param);
696}
697
698int fill_get_data_req_step(unsigned char *buf, short code, int offset)
699{
700	unsigned char param[10];
701	memset(param, 0, sizeof(param));
702	param[0] = (code >> 8) & 0xff;
703	param[1] = code & 0xff;
704	param[2] = (offset >> 24) & 0xff;
705	param[3] = (offset >> 16) & 0xff;
706	param[4] = (offset >> 8) & 0xff;
707	param[5] = offset & 0xff;
708	return fill_normal_config_req(buf, 0x03, 0x14, sizeof(param), param);
709}
710
711int fill_rf_on_req(unsigned char *buf) // * Ok
712{
713	return fill_normal_config_req(buf, 0x00, 0x06, 0, NULL);
714}
715
716int fill_rf_off_req(unsigned char *buf) // * Ok
717{
718	return fill_normal_config_req(buf, 0x00, 0x04, 0, NULL);
719}
720
721int fill_eap_key_req(unsigned char *buf, unsigned char *key, int key_len)  //	EAP	key
722{
723	unsigned char param[key_len+2];
724	param[0] = 0x02; // key_len / 32
725	param[1] = key_len;
726	memcpy(param + 0x02, key, key_len);
727	return fill_normal_config_req(buf, 0x00, 0x01, sizeof(param), param);
728}
729
730int fill_image_dl_req(unsigned char *buf, int code, int offset, unsigned char *data, int len)
731{
732	unsigned char param[len+6];
733	param[0] = (code >> 8) & 0xff;
734	param[1] = code & 0xff;
735	param[2] = (offset >> 24) & 0xff;
736	param[3] = (offset >> 16) & 0xff;
737	param[4] = (offset >> 8) & 0xff;
738	param[5] = offset & 0xff;
739	memcpy(param + 6, data, len);
740	return fill_normal_config_req(buf, 0x03, 0x10, sizeof(param), param);
741}
742/*
743int fill_some_req(unsigned char *buf) // * Ok  X3  O_O
744{
745	unsigned char param[] = {   0x02, 0x40, 0xa2, 0x89, 0x17, 0x0a, 0x37, 0xfe, 0xf9, 0x06, 0x0b, 0xaa, \
746		0x24, 0x8b, 0x8b, 0xcd, 0xf2, 0xd4, 0xd3, 0xea, 0xdb, 0xcb, 0xf7, 0xf9, 0xce, 0x16, 0x3e, 0xc9, \
747		0x60, 0x74, 0x53, 0x69, 0x55, 0xe5, 0x5f, 0x19, 0x42, 0x56, 0x4e, 0xf9, 0x65, 0x5d, 0x32, 0x77, \
748        0xac, 0xb1, 0x9b, 0xa3, 0xa0, 0xd3, 0xef, 0xdf, 0x81, 0x0b, 0x69, 0x27, 0x76, 0xeb, 0xac, 0xd0, \
749		0x2c, 0x5c, 0xaf, 0x3f, 0xfb, 0x4e};
750	return fill_normal_config_req(buf, 0x00, 0x01, sizeof(param), param);
751}
752*/
753int fill_debug_req(unsigned char *buf) // OK
754{
755	unsigned char param[] = {0xb1, 0x01, 0x00}; // last bit 00 = Normal 01 = Test
756	return fill_normal_config_req(buf, 0x00, 0x01, sizeof(param), param);
757}
758/*
759int fill_auth_policy_req(unsigned char *buf)
760{
761	return fill_normal_config_req(buf, 0x20, 0x8, 0x0, NULL);
762}
763
764int fill_auth_method_req(unsigned char *buf)
765{
766	return fill_normal_config_req(buf, 0x20, 0xc, 0x0, NULL);
767}
768
769int fill_auth_set_cmd(unsigned char *buf, char *netid)
770{
771	short netid_len = strlen(netid) + 1;
772	unsigned char param[netid_len + 4];
773	param[0] = 0x0;
774	param[1] = 0x10;
775	param[2] = netid_len >> 8;
776	param[3] = netid_len & 0xff;
777	memcpy(param + 4, netid, netid_len);
778	return fill_normal_config_req(buf, 0x20, 0x20, sizeof(param), param);
779}
780*/
781int fill_dm_cmd_req(unsigned char *buf, char *cmd)
782{
783	unsigned char param[strlen(cmd)+1];
784	memcpy(param, cmd, strlen(cmd));
785	param[strlen(cmd)] = '\n';
786
787//	printf("DM command: %s", param);
788
789	return fill_normal_config_req(buf, 0x03, 0x0c, sizeof(param), param);
790}
791
792int fill_find_network_req(unsigned char *buf, struct wimax_dev_status *dev) // OK
793{
794	unsigned char param[6];
795	param[0] = 0x02;
796	param[1] = 0xd2;
797	param[2] = 0x03;
798	param[0x03]	= (dev->nspid&0xff0000)>>16;
799	param[0x04]	= (dev->nspid&0xff00)>>8;
800	param[0x05]	= (dev->nspid&0xff);
801	//memcpy(param + 0x03, dev->nspid, 0x03);
802	return fill_normal_config_req(buf, 0x01, 0x0d, sizeof(param), param);
803}
804
805int fill_connect_req(unsigned char *buf, struct wimax_dev_status *dev) // OK
806{
807	unsigned char param[0x0a];
808	param[0x00] = 0xd2;
809	param[0x01] = 0x03;
810	//memcpy(param + 0x02, dev->nspid, 0x03);
811	param[0x02]	= (dev->nspid&0xff0000)>>16;
812	param[0x03]	= (dev->nspid&0xff00)>>8;
813	param[0x04]	= (dev->nspid&0xff);
814	param[0x05] = 0xd6;
815	param[0x06] = 0x03;
816	param[0x07]	= (dev->napid&0xff0000)>>16;
817	param[0x08]	= (dev->napid&0xff00)>>8;
818	param[0x09]	= (dev->napid&0xff);
819	//memcpy(param + 0x07, dev->napid, 0x03);
820	return fill_normal_config_req(buf, 0x01, 0x10, sizeof(param), param);
821}
822
823
824int fill_eap_server_rx_req(unsigned char *buf,unsigned char *param, int param_len)  //	EAP	!!!
825{
826	return fill_normal_config_req(buf, 0x02, 0x00, param_len, param);
827}
828
829
830int fill_connection_params_req(unsigned char *buf) // Ok
831{
832	//unsigned char param[] = {0x01, 0x60, 0x61, 0x6a, 0x7f};
833	unsigned char param[] = {0x60, 0x61, 0x72, 0x71, 0x6a, 0x7f};
834	return fill_normal_config_req(buf, 0x00, 0x02, sizeof(param), param);
835}
836/*
837int fill_state_req(unsigned char *buf)
838{
839	return fill_normal_config_req(buf, 0x1, 0xb, 0x0, NULL);
840}
841*//*
842int fill_network_list_req(unsigned char *buf)
843{
844	unsigned char param[0x2] = {0x00, 0x00};
845	return fill_normal_config_req(buf, 0x24, 0x1, sizeof(param), param);
846}
847*/
848
849int get_header_len()
850{
851	return HEADER_LENGTH;
852}
853
854int fill_data_packet_header(unsigned char *buf, int body_len) // Ok
855{
856	fill_outgoing_packet_header(buf, 0x02, 0x02, body_len);
857	return HEADER_LENGTH + body_len;
858}
859
860