1 /*******************************************************************
\r
4 l2cap.c - fce for operation L2CAP protocol (build L2CAP packet)
\r
5 and for saving data to data queue
\r
7 Copyright (C) 2006 by Petr Kovacik petr_kovacik@gmail.com
\r
9 *******************************************************************/
\r
17 #include <cpu_def.h>
\r
18 #include <h8s2638h.h>
\r
19 #include <periph/sci_rs232.h>
\r
20 #include <system_def.h>
\r
29 #include "inline_fce.h"
\r
30 #include "bth_inface.h"
\r
31 #include "bth_fce_out.h"
\r
35 * pointery na funkce, ktere se vykonavaji v zavislosti na parametru
\r
37 typedef int (*l2cap_code_fce_def)(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan);
\r
38 l2cap_code_fce_def l2cap_code_fce[]={
\r
39 l2cap_none,l2cap_cod_command_rej,l2cap_cod_conn_req, l2cap_cod_conn_rsp, l2cap_cod_conf_req, l2cap_cod_conf_rsp,
\r
40 l2cap_cod_disconn_req, l2cap_cod_disconn_rsp, l2cap_cod_echo_req, l2cap_cod_echo_rsp, l2cap_cod_info_req,
\r
41 l2cap_cod_info_rsp};
\r
42 #define L2CAP_SUM_FC (sizeof(l2cap_code_fce)/sizeof(l2cap_code_fce[0]))
\r
45 /*----------------------- funkce zavisle na code -----------------------------------*/
\r
48 * funkce prohledava kanaly pripoj. zazizeni dev_num a hleda zadany kanal
\r
50 inline int l2cap_find_dcid(int dcid, int dev_num )
\r
53 for(i=1;i<L2CAP_NUM_OF_CANAL;i++)
\r
55 if(bth_connected[dev_num]->dcid[i]==dcid)
\r
64 /*------------------------------ pomocne funkce --------------------------------*/
\r
66 int l2cap_add_to_send_buffer(uint8_t *bth_p)
\r
68 if(bth_pole_adrr_comm_packet[bth_com_buf_info.aktual]!=NULL)
\r
70 bth_pole_adrr_comm_packet[bth_com_buf_info.aktual]=bth_p;
\r
72 /*nastaveni pozice v poli command prikazu pro pristi prikaz. Moznost zapisu (adresa v poli = NULL)
\r
73 se overuje, az pri samotnem ukladani */
\r
74 if(bth_com_buf_info.aktual<(LENCOMMAND-2)){bth_com_buf_info.aktual++;}
\r
75 else{ bth_com_buf_info.aktual=0;};
\r
80 * neexistujici funkce - nemeli by nikdy nastat
\r
82 int l2cap_none(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan)
\r
90 * dekodovani signaling paketu a volani vyse napsanych fci (pointery na fce)
\r
92 int l2cap_signaling(uint8_t *bth_p, uint16_t size,int dev_num)
\r
94 l2cap_cmd_hdr bth_q;
\r
96 store16(bth_q.code,*((uint8_t*)bth_p+L2CAP_CMD_HDR____code));
\r
97 store16(bth_connected[dev_num]->ident,*((uint8_t*)bth_p+L2CAP_CMD_HDR____ident));
\r
98 __bthtomc16((uint8_t*)&(bth_q.len),((uint8_t*)bth_p+L2CAP_CMD_HDR____len));
\r
100 if(bth_q.code<L2CAP_SUM_FC)
\r
101 { /*odskok na obsluznou fci*/
\r
102 l2cap_code_fce[bth_q.code]((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE, bth_q.len,dev_num, 0);
\r
108 /*----------------------- funkce zavisle na code -----------------------------------*/
\r
113 int l2cap_cod_command_rej(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x01
\r
120 * Connection request
\r
122 int l2cap_cod_conn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x02
\r
124 l2cap_conn_req bth_q;
\r
127 /*zde se paket sestavuje - tj. jedna se o zarizeni, ktere chce vytvorit novy kanal*/
\r
132 /*lokalni zarizeni obdrzelo paket 0x02*/
\r
133 __bthtomc16((uint8_t*)&(bth_q.psm),((uint8_t*)bth_p+L2CAP_CONN_REQ____psm));
\r
134 __bthtomc16((uint8_t*)&(bth_q.scid),((uint8_t*)bth_p+L2CAP_CONN_REQ____scid));
\r
135 /*SCID je v tomto pripade DCID, protoze vysilajici strana si tento kanal zvolila jako SCID. Uloha je brana z
\r
136 pohledu daneho zarizeni (ktere paket prijalo) tudiz se jedna o DCID*/
\r
138 pos_chan=bth_add_chanal_dcid(dev_num, bth_q.scid); //pridam DCID vzdaleneho zarizeni
\r
140 /*sestavim paket, kterym odpovidam*/
\r
141 l2cap_cod_conn_rsp(NULL,0,dev_num,pos_chan);
\r
142 bth_local_info.busy=0;
\r
148 Connection response
\r
150 int l2cap_cod_conn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x03
\r
152 l2cap_conn_req bth_q;
\r
154 uint16_t result=L2CAP_CR_SUCCESS;
\r
156 uint8_t *typ_hci_paket;
\r
157 hci_acl_hdr *hci_headr;
\r
158 l2cap_hdr *l2cap_headr;
\r
159 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
160 l2cap_conn_rsp *l2cap_conn_response;
\r
163 /*zarizeni obdrzelo od vzdaleneho zarizeni paket 0x03*/
\r
164 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE);
\r
165 bth_r=malloc(hp_size);
\r
167 typ_hci_paket=(uint8_t*)bth_r;
\r
168 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
169 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
170 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
171 l2cap_conn_response=(l2cap_conn_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
173 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
174 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|bth_connected[dev_num]->handle));
\r
175 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
177 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
178 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
179 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONN_RSP);
\r
182 if(pos_chan>-1) //kanal daneho zarizeni, jeste neexistuje, tj. zalozim ho
\r
184 (bth_connected[dev_num])->scid[pos_chan]=(0x0040+pos_chan+1);
\r
185 /*dcin - vzdal. zarizeni, ktere */
\r
186 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),(0x0040+pos_chan+1));
\r
189 result=htobs(L2CAP_CR_PEND); status=htobs(L2CAP_CS_NO_INFO);
\r
190 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),0);
\r
193 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),((bths_connect_bluet*)bth_connected[dev_num])->ident);
\r
194 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),L2CAP_CONN_RSP_SIZE);
\r
195 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____scid),((bths_connect_bluet*)bth_connected[dev_num])->dcid[pos_chan]);
\r
197 if(l2cap_find_dcid(bth_q.scid, dev_num)>=0) //prohledam vsechna DCID (SCID vzdaleneho zarizeni, jeslti uz ho nepouziva)
\r
199 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),htobs(L2CAP_CR_SUCCESS));
\r
200 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),htobs(L2CAP_CS_NO_INFO));
\r
202 else//zarizeni uz kanal pouziva, tj. odrekni spojeni s prislusnzym chyb. kodem
\r
204 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),result);
\r
205 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),status);
\r
207 /*pripravim data do vysilaciho bufferu*/
\r
208 return(l2cap_add_to_send_buffer(bth_r));
\r
212 /*lok. zarizeni vysila vzdalenemu zarizeni paket 0x03 - zada o kanal*/
\r
220 int l2cap_cod_conf_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x04
\r
222 l2cap_conf_req bth_q;
\r
224 uint8_t *typ_hci_paket;
\r
225 hci_acl_hdr *hci_headr;
\r
226 l2cap_hdr *l2cap_headr;
\r
227 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
228 l2cap_conf_req *l2cap_conf_request;
\r
235 __bthtomc16((uint8_t*)&(bth_q.dcid),((uint8_t*)bth_p+L2CAP_CONF_REQ____dcid));
\r
236 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_REQ____flags));
\r
237 //jeste nejaka data .... - v nasem pripade se zadna nezpracovavaji
\r
239 pos_chan=bth_find_chanal_scid(dev_num, bth_q.dcid);
\r
240 l2cap_cod_conf_rsp(NULL, 0, dev_num, pos_chan); //0x05
\r
242 /***************sestavim paket, kterym posilam responce kod = 0x04 masterovi*************/
\r
243 /*nastaveni adres pro casti paketu + naplneni jednotlivych polozek*/
\r
244 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE);
\r
245 bth_r=malloc(hp_size);
\r
247 typ_hci_paket=(uint8_t*)bth_r;
\r
248 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
249 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
250 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
251 l2cap_conf_request=(l2cap_conf_req *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
254 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
255 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
256 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
258 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
259 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
261 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_REQ);
\r
262 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
263 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_REQ_SIZE));
\r
265 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____dcid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
266 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____flags),0);
\r
267 //posledni polozka jsou data - nebubu posilat v tomto paketu
\r
269 /******************* umisteni do vysilaciho bufferu **************************/
\r
270 l2cap_add_to_send_buffer(bth_r);
\r
280 int l2cap_cod_conf_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x05
\r
282 l2cap_conf_rsp bth_q;
\r
284 uint8_t *typ_hci_paket;
\r
285 hci_acl_hdr *hci_headr;
\r
286 l2cap_hdr *l2cap_headr;
\r
287 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
288 l2cap_conf_rsp *l2cap_conf_response;
\r
292 /*sestavim paket, kterym odpovidam*/
\r
293 /*nastaveni adres pro casti paketu + naplneni jednotlivych polozek*/
\r
294 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE);
\r
295 bth_r=malloc(hp_size);
\r
297 typ_hci_paket=(uint8_t*)bth_r;
\r
298 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
299 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
300 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
301 l2cap_conf_response=(l2cap_conf_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
303 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
304 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
305 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
307 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
308 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
310 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_RSP);
\r
311 (bth_connected[dev_num])->ident++;
\r
312 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
313 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_RSP_SIZE));
\r
315 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____scid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
316 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____flags),0);
\r
317 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____result),0);
\r
318 //posledni polozka jsou data - nebubu posilat v tomto paketu
\r
321 /******************* umisteni do vysilaciho bufferu **************************/
\r
322 return(l2cap_add_to_send_buffer(bth_r));
\r
326 __bthtomc16((uint8_t*)&(bth_q.scid),((uint8_t*)bth_p+L2CAP_CONF_RSP____scid));
\r
327 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_RSP____flags));
\r
328 __bthtomc16((uint8_t*)&(bth_q.result),((uint8_t*)bth_p+L2CAP_CONF_RSP____result));
\r
329 return (bth_q.result);;
\r
334 Disconnection request
\r
336 int l2cap_cod_disconn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x06
\r
342 Disconnection response
\r
344 int l2cap_cod_disconn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x07
\r
353 int l2cap_cod_echo_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x08
\r
362 int l2cap_cod_echo_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x09
\r
370 int l2cap_cod_info_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0a
\r
376 Information request
\r
378 int l2cap_cod_info_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0b
\r
383 /*----------------------- send data ----------------------------*/
\r
386 * zabali data z dat. zasobniku do peketu a da k odeslani
\r
388 int l2cap_send_data(int inx_handle, int inx_chanal)
\r
391 uint8_t *typ_hci_paket;
\r
392 hci_acl_hdr *hci_headr;
\r
393 l2cap_hdr *l2cap_headr;
\r
397 int hp_size,size=0;
\r
398 uint16_t handle, chanal;
\r
401 if(bth_connected[inx_handle]==NULL) return (-1);
\r
402 if((bth_connected[inx_handle])->dcid[inx_chanal]==0) return (-1);
\r
404 /*cteni z vysilaciho zasobniku, skusmo 1 znak*/
\r
405 zn=bth_inface_t_isr(0);
\r
408 handle = ((bths_connect_bluet*)bth_connected[inx_handle])->handle;
\r
409 handle=(handle | htobs(0x2000));
\r
410 chanal = (bth_connected[inx_handle])->dcid[inx_chanal];
\r
412 /*vytvoreni prostoru pro paket + prideleni adres pro jednotlive casti L2CAP paketu*/
\r
413 hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+BTH_INFACE_BUF_LEN);
\r
414 bth_r=malloc(hp_size);
\r
416 typ_hci_paket=bth_r; //pozice v buff, ktera je prirazena paketu
\r
417 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
418 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
419 data=((uint8_t*)l2cap_headr+L2CAP_HDR_SIZE); //pointer na data
\r
421 /*-----------------------------DATA FOR SENDING TO PC --------------------------*/
\r
422 *((uint8_t*)data+size)=(uint8_t)zn;
\r
424 /*cyklicke cteni dalsich znaku a skladani do paketu*/
\r
425 while ((zn=bth_inface_t_isr(0))>=0)
\r
427 *((uint8_t*)data+size)=(uint8_t)zn;
\r
431 else {return (0);}; //data nejsou v zasobniku
\r
433 /*sestavim zbytek paketu, kterym odpovidam tj. naplneni jednotlivych polozek*/
\r
434 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
435 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,handle);
\r
436 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,(htobs(L2CAP_CMD_HDR_SIZE)+size));
\r
438 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len),size);
\r
439 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),chanal);
\r
441 // VypisHexa((void*)typ_hci_paket,16);
\r
442 // bth_local_info.busy=0;
\r
443 return(l2cap_add_to_send_buffer(bth_r));
\r