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
26 #include "inline_fce.h"
\r
27 #include "bth_inface.h"
\r
28 #include "bth_fce_out.h"
\r
32 * pointers to functions, which are executed depending on a parameter
\r
34 typedef int (*l2cap_code_fce_def)(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan);
\r
35 l2cap_code_fce_def l2cap_code_fce[]={
\r
36 l2cap_none,l2cap_cod_command_rej,l2cap_cod_conn_req, l2cap_cod_conn_rsp, l2cap_cod_conf_req, l2cap_cod_conf_rsp,
\r
37 l2cap_cod_disconn_req, l2cap_cod_disconn_rsp, l2cap_cod_echo_req, l2cap_cod_echo_rsp, l2cap_cod_info_req,
\r
38 l2cap_cod_info_rsp};
\r
39 #define L2CAP_SUM_FC (sizeof(l2cap_code_fce)/sizeof(l2cap_code_fce[0]))
\r
42 /*----------------------- function depending on code -----------------------------------*/
\r
45 * Search the cannels of the connected device dev_num and search the channel dcid
\r
47 static inline int l2cap_find_dcid(int dcid, int dev_num )
\r
50 for(i=1;i<L2CAP_NUM_OF_CANAL;i++)
\r
52 if(bth_connected[dev_num]->dcid[i]==dcid)
\r
61 /*------------------------------ auxiliary functions --------------------------------*/
\r
63 int l2cap_add_to_send_buffer(uint8_t *bth_p)
\r
65 if(bth_array_adrr_comm_packet[bth_com_buf_info.aktual]!=NULL)
\r
67 bth_array_adrr_comm_packet[bth_com_buf_info.aktual]=bth_p;
\r
69 /*set the position in command array for the next command. If it is possible to write there (if the pointer = NULL) is checked by the writer. .
\r
71 nastaveni pozice v poli command prikazu pro pristi prikaz. Moznost zapisu (adresa v poli = NULL)
\r
72 se overuje, az pri samotnem ukladani */
\r
73 if(bth_com_buf_info.aktual<(LENCOMMAND-2)){bth_com_buf_info.aktual++;}
\r
74 else{ bth_com_buf_info.aktual=0;};
\r
79 * Nonexisting function - should never happend
\r
81 int l2cap_none(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan)
\r
89 * decoding of the signaling packet and calling of the above functions
\r
91 int l2cap_signaling(uint8_t *bth_p, uint16_t size,int dev_num)
\r
93 l2cap_cmd_hdr bth_q;
\r
95 store16(bth_q.code,*((uint8_t*)bth_p+L2CAP_CMD_HDR____code));
\r
96 store16(bth_connected[dev_num]->ident,*((uint8_t*)bth_p+L2CAP_CMD_HDR____ident));
\r
97 __bthtomc16((uint8_t*)&(bth_q.len),((uint8_t*)bth_p+L2CAP_CMD_HDR____len));
\r
99 if(bth_q.code<L2CAP_SUM_FC)
\r
100 { /*jump to the handling functions*/
\r
101 l2cap_code_fce[bth_q.code]((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE, bth_q.len,dev_num, 0);
\r
107 /*----------------------- functions depending on code -----------------------------------*/
\r
112 int l2cap_cod_command_rej(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x01
\r
119 * Connection request
\r
121 int l2cap_cod_conn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x02
\r
123 l2cap_conn_req bth_q;
\r
126 /*the packet is built here - ie. this is the device that wants to create a new channel*/
\r
127 /*zde se paket sestavuje - tj. jedna se o zarizeni, ktere chce vytvorit novy kanal*/
\r
132 /*local device receives packet 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 is in this case DCID, because sending side choosed thich channel as SCID. This is viewed from the point of view of
\r
136 receiving device, so this is DCID. */
\r
137 /*SCID je v tomto pripade DCID, protoze vysilajici strana si tento kanal zvolila jako SCID. Uloha je brana z
\r
138 pohledu daneho zarizeni (ktere paket prijalo) tudiz se jedna o DCID*/
\r
140 pos_chan=bth_add_chanal_dcid(dev_num, bth_q.scid); //add DCID of the remote device
\r
142 /*build the response packet*/
\r
143 l2cap_cod_conn_rsp(NULL,0,dev_num,pos_chan);
\r
144 bth_local_info.busy=0;
\r
150 Connection response
\r
152 int l2cap_cod_conn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x03
\r
154 l2cap_conn_req bth_q;
\r
156 uint16_t result=L2CAP_CR_SUCCESS;
\r
158 uint8_t *typ_hci_paket;
\r
159 hci_acl_hdr *hci_headr;
\r
160 l2cap_hdr *l2cap_headr;
\r
161 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
162 l2cap_conn_rsp *l2cap_conn_response;
\r
165 /*the device received packet 0x03 from the remote device*/
\r
166 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE);
\r
167 bth_r=malloc(hp_size);
\r
169 typ_hci_paket=(uint8_t*)bth_r;
\r
170 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer to head
\r
171 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer to parametrs
\r
172 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
173 l2cap_conn_response=(l2cap_conn_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
175 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
176 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|bth_connected[dev_num]->handle));
\r
177 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
179 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
180 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
181 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONN_RSP);
\r
184 if(pos_chan>-1) //the channel of that device don't exists. We will create it
\r
186 (bth_connected[dev_num])->scid[pos_chan]=(0x0040+pos_chan+1);
\r
187 /*dcin - remote device, which */
\r
188 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),(0x0040+pos_chan+1));
\r
191 result=htobs(L2CAP_CR_PEND); status=htobs(L2CAP_CS_NO_INFO);
\r
192 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),0);
\r
195 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),((bths_connect_bluet*)bth_connected[dev_num])->ident);
\r
196 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),L2CAP_CONN_RSP_SIZE);
\r
197 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____scid),((bths_connect_bluet*)bth_connected[dev_num])->dcid[pos_chan]);
\r
199 if(l2cap_find_dcid(bth_q.scid, dev_num)>=0) //search all the DCID (SCID of remote device, if it is not used)
\r
201 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),htobs(L2CAP_CR_SUCCESS));
\r
202 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),htobs(L2CAP_CS_NO_INFO));
\r
204 else//the device uses the channel, se reply with an apropriate error code
\r
206 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),result);
\r
207 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),status);
\r
209 /*prepare data to sending buffer*/
\r
210 return(l2cap_add_to_send_buffer(bth_r));
\r
214 /*local device sends to the remote device paket 0x03 - apply for a channel*/
\r
222 int l2cap_cod_conf_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x04
\r
224 l2cap_conf_req bth_q;
\r
226 uint8_t *typ_hci_paket;
\r
227 hci_acl_hdr *hci_headr;
\r
228 l2cap_hdr *l2cap_headr;
\r
229 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
230 l2cap_conf_req *l2cap_conf_request;
\r
237 __bthtomc16((uint8_t*)&(bth_q.dcid),((uint8_t*)bth_p+L2CAP_CONF_REQ____dcid));
\r
238 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_REQ____flags));
\r
239 //yet some data .... - in our case, nothing is processed
\r
241 pos_chan=bth_find_chanal_scid(dev_num, bth_q.dcid);
\r
242 l2cap_cod_conf_rsp(NULL, 0, dev_num, pos_chan); //0x05
\r
244 /***************build the packet, by which we send response code = 0x04 to the master*************/
\r
245 /*setting of addresses for the parts of the packet + filling of inidividual fields*/
\r
246 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE);
\r
247 bth_r=malloc(hp_size);
\r
249 typ_hci_paket=(uint8_t*)bth_r;
\r
250 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer to head
\r
251 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer to parametrs
\r
252 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
253 l2cap_conf_request=(l2cap_conf_req *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
256 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
257 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
258 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
260 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
261 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
263 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_REQ);
\r
264 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
265 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_REQ_SIZE));
\r
267 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____dcid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
268 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____flags),0);
\r
269 //the last item are data - they are not sent in this packet
\r
271 /******************* put it to send buffer **************************/
\r
272 l2cap_add_to_send_buffer(bth_r);
\r
282 int l2cap_cod_conf_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x05
\r
284 l2cap_conf_rsp bth_q;
\r
286 uint8_t *typ_hci_paket;
\r
287 hci_acl_hdr *hci_headr;
\r
288 l2cap_hdr *l2cap_headr;
\r
289 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
290 l2cap_conf_rsp *l2cap_conf_response;
\r
294 /*build the response packet*/
\r
295 /*setup the adresses for parts of the packet + filling of individual fields*/
\r
296 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE);
\r
297 bth_r=malloc(hp_size);
\r
299 typ_hci_paket=(uint8_t*)bth_r;
\r
300 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
301 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
302 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
303 l2cap_conf_response=(l2cap_conf_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
305 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
306 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
307 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
309 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
310 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
312 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_RSP);
\r
313 (bth_connected[dev_num])->ident++;
\r
314 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
315 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_RSP_SIZE));
\r
317 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____scid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
318 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____flags),0);
\r
319 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____result),0);
\r
320 //posledni polozka jsou data - nebubu posilat v tomto paketu //same as in previous func
\r
323 /******************* umisteni do vysilaciho bufferu **************************/
\r
324 return(l2cap_add_to_send_buffer(bth_r));
\r
328 __bthtomc16((uint8_t*)&(bth_q.scid),((uint8_t*)bth_p+L2CAP_CONF_RSP____scid));
\r
329 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_RSP____flags));
\r
330 __bthtomc16((uint8_t*)&(bth_q.result),((uint8_t*)bth_p+L2CAP_CONF_RSP____result));
\r
331 return (bth_q.result);;
\r
336 Disconnection request
\r
338 int l2cap_cod_disconn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x06
\r
344 Disconnection response
\r
346 int l2cap_cod_disconn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x07
\r
355 int l2cap_cod_echo_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x08
\r
364 int l2cap_cod_echo_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x09
\r
372 int l2cap_cod_info_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0a
\r
378 Information request
\r
380 int l2cap_cod_info_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0b
\r
385 /*----------------------- send data ----------------------------*/
\r
388 * zabali data z dat. zasobniku do peketu a da k odeslani
\r
390 int l2cap_send_data(int inx_handle, int inx_chanal)
\r
393 uint8_t *typ_hci_paket;
\r
394 hci_acl_hdr *hci_headr;
\r
395 l2cap_hdr *l2cap_headr;
\r
399 int hp_size,size=0;
\r
400 uint16_t handle, chanal;
\r
403 if(bth_connected[inx_handle]==NULL) return (-1);
\r
404 if((bth_connected[inx_handle])->dcid[inx_chanal]==0) return (-1);
\r
406 /*reading from sending buffer, try 1 character*/
\r
407 zn=bth_inface_t_isr(0);
\r
410 handle = ((bths_connect_bluet*)bth_connected[inx_handle])->handle;
\r
411 handle=(handle | htobs(0x2000));
\r
412 chanal = (bth_connected[inx_handle])->dcid[inx_chanal];
\r
414 /*make space for the packer + assign adresses for individual parts of L2CAP packet*/
\r
415 hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+BTH_INFACE_BUF_LEN);
\r
416 bth_r=malloc(hp_size);
\r
418 typ_hci_paket=bth_r; //pozice v buff, ktera je prirazena paketu
\r
419 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
420 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
421 data=((uint8_t*)l2cap_headr+L2CAP_HDR_SIZE); //pointer na data
\r
423 /*-----------------------------DATA FOR SENDING TO PC --------------------------*/
\r
424 *((uint8_t*)data+size)=(uint8_t)zn;
\r
426 /*cyclic reading of the folowing characters and building of the packet*/
\r
427 while ((zn=bth_inface_t_isr(0))>=0)
\r
429 *((uint8_t*)data+size)=(uint8_t)zn;
\r
433 else {return (0);}; //data are not in the queue
\r
435 /*build the rest of the response packet ie. fill the fields*/
\r
436 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
437 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,handle);
\r
438 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,(htobs(L2CAP_CMD_HDR_SIZE)+size));
\r
440 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len),size);
\r
441 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),chanal);
\r
443 // VypisHexa((void*)typ_hci_paket,16);
\r
444 // bth_local_info.busy=0;
\r
445 return(l2cap_add_to_send_buffer(bth_r));
\r