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 * pointers to functions, which are executed depending on a parameter
\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 /*----------------------- function depending on code -----------------------------------*/
\r
48 * Search the cannels of the connected device dev_num and search the channel dcid
\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 /*------------------------------ auxiliary functions --------------------------------*/
\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 /*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
74 nastaveni pozice v poli command prikazu pro pristi prikaz. Moznost zapisu (adresa v poli = NULL)
\r
75 se overuje, az pri samotnem ukladani */
\r
76 if(bth_com_buf_info.aktual<(LENCOMMAND-2)){bth_com_buf_info.aktual++;}
\r
77 else{ bth_com_buf_info.aktual=0;};
\r
82 * Nonexisting function - should never happend
\r
84 int l2cap_none(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan)
\r
92 * decoding of the signaling packet and calling of the above functions
\r
94 int l2cap_signaling(uint8_t *bth_p, uint16_t size,int dev_num)
\r
96 l2cap_cmd_hdr bth_q;
\r
98 store16(bth_q.code,*((uint8_t*)bth_p+L2CAP_CMD_HDR____code));
\r
99 store16(bth_connected[dev_num]->ident,*((uint8_t*)bth_p+L2CAP_CMD_HDR____ident));
\r
100 __bthtomc16((uint8_t*)&(bth_q.len),((uint8_t*)bth_p+L2CAP_CMD_HDR____len));
\r
102 if(bth_q.code<L2CAP_SUM_FC)
\r
103 { /*jump to the handling functions*/
\r
104 l2cap_code_fce[bth_q.code]((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE, bth_q.len,dev_num, 0);
\r
110 /*----------------------- functions depending on code -----------------------------------*/
\r
115 int l2cap_cod_command_rej(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x01
\r
122 * Connection request
\r
124 int l2cap_cod_conn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x02
\r
126 l2cap_conn_req bth_q;
\r
129 /*the packet is built here - ie. this is the device that wants to create a new channel*/
\r
130 /*zde se paket sestavuje - tj. jedna se o zarizeni, ktere chce vytvorit novy kanal*/
\r
135 /*local device receives packet 0x02*/
\r
136 __bthtomc16((uint8_t*)&(bth_q.psm),((uint8_t*)bth_p+L2CAP_CONN_REQ____psm));
\r
137 __bthtomc16((uint8_t*)&(bth_q.scid),((uint8_t*)bth_p+L2CAP_CONN_REQ____scid));
\r
138 /*SCID is in this case DCID, because sending side choosed thich channel as SCID. This is viewed from the point of view of
\r
139 receiving device, so this is DCID. */
\r
140 /*SCID je v tomto pripade DCID, protoze vysilajici strana si tento kanal zvolila jako SCID. Uloha je brana z
\r
141 pohledu daneho zarizeni (ktere paket prijalo) tudiz se jedna o DCID*/
\r
143 pos_chan=bth_add_chanal_dcid(dev_num, bth_q.scid); //add DCID of the remote device
\r
145 /*build the response packet*/
\r
146 l2cap_cod_conn_rsp(NULL,0,dev_num,pos_chan);
\r
147 bth_local_info.busy=0;
\r
153 Connection response
\r
155 int l2cap_cod_conn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x03
\r
157 l2cap_conn_req bth_q;
\r
159 uint16_t result=L2CAP_CR_SUCCESS;
\r
161 uint8_t *typ_hci_paket;
\r
162 hci_acl_hdr *hci_headr;
\r
163 l2cap_hdr *l2cap_headr;
\r
164 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
165 l2cap_conn_rsp *l2cap_conn_response;
\r
168 /*the device received packet 0x03 from the remote device*/
\r
169 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE);
\r
170 bth_r=malloc(hp_size);
\r
172 typ_hci_paket=(uint8_t*)bth_r;
\r
173 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer to head
\r
174 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer to parametrs
\r
175 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
176 l2cap_conn_response=(l2cap_conn_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
178 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
179 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|bth_connected[dev_num]->handle));
\r
180 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
182 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONN_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
183 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
184 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONN_RSP);
\r
187 if(pos_chan>-1) //the channel of that device don't exists. We will create it
\r
189 (bth_connected[dev_num])->scid[pos_chan]=(0x0040+pos_chan+1);
\r
190 /*dcin - remote device, which */
\r
191 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),(0x0040+pos_chan+1));
\r
194 result=htobs(L2CAP_CR_PEND); status=htobs(L2CAP_CS_NO_INFO);
\r
195 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____dcid),0);
\r
198 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),((bths_connect_bluet*)bth_connected[dev_num])->ident);
\r
199 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),L2CAP_CONN_RSP_SIZE);
\r
200 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____scid),((bths_connect_bluet*)bth_connected[dev_num])->dcid[pos_chan]);
\r
202 if(l2cap_find_dcid(bth_q.scid, dev_num)>=0) //search all the DCID (SCID of remote device, if it is not used)
\r
204 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),htobs(L2CAP_CR_SUCCESS));
\r
205 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),htobs(L2CAP_CS_NO_INFO));
\r
207 else//the device uses the channel, se reply with an apropriate error code
\r
209 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____result),result);
\r
210 store_le16((uint16_t*)((uint8_t*)l2cap_conn_response+L2CAP_CONN_RSP____status),status);
\r
212 /*prepare data to sending buffer*/
\r
213 return(l2cap_add_to_send_buffer(bth_r));
\r
217 /*local device sends to the remote device paket 0x03 - apply for a channel*/
\r
225 int l2cap_cod_conf_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x04
\r
227 l2cap_conf_req bth_q;
\r
229 uint8_t *typ_hci_paket;
\r
230 hci_acl_hdr *hci_headr;
\r
231 l2cap_hdr *l2cap_headr;
\r
232 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
233 l2cap_conf_req *l2cap_conf_request;
\r
240 __bthtomc16((uint8_t*)&(bth_q.dcid),((uint8_t*)bth_p+L2CAP_CONF_REQ____dcid));
\r
241 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_REQ____flags));
\r
242 //yet some data .... - in our case, nothing is processed
\r
244 pos_chan=bth_find_chanal_scid(dev_num, bth_q.dcid);
\r
245 l2cap_cod_conf_rsp(NULL, 0, dev_num, pos_chan); //0x05
\r
247 /***************build the packet, by which we send response code = 0x04 to the master*************/
\r
248 /*setting of addresses for the parts of the packet + filling of inidividual fields*/
\r
249 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE);
\r
250 bth_r=malloc(hp_size);
\r
252 typ_hci_paket=(uint8_t*)bth_r;
\r
253 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer to head
\r
254 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer to parametrs
\r
255 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
256 l2cap_conf_request=(l2cap_conf_req *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
259 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
260 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
261 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
263 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_REQ_SIZE+L2CAP_CMD_HDR_SIZE));
\r
264 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
266 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_REQ);
\r
267 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
268 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_REQ_SIZE));
\r
270 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____dcid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
271 store_le16((uint16_t*)((uint8_t*)l2cap_conf_request+L2CAP_CONF_REQ____flags),0);
\r
272 //the last item are data - they are not sent in this packet
\r
274 /******************* put it to send buffer **************************/
\r
275 l2cap_add_to_send_buffer(bth_r);
\r
285 int l2cap_cod_conf_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x05
\r
287 l2cap_conf_rsp bth_q;
\r
289 uint8_t *typ_hci_paket;
\r
290 hci_acl_hdr *hci_headr;
\r
291 l2cap_hdr *l2cap_headr;
\r
292 l2cap_cmd_hdr *l2cap_cmd_headr;
\r
293 l2cap_conf_rsp *l2cap_conf_response;
\r
297 /*build the response packet*/
\r
298 /*setup the adresses for parts of the packet + filling of individual fields*/
\r
299 int hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE);
\r
300 bth_r=malloc(hp_size);
\r
302 typ_hci_paket=(uint8_t*)bth_r;
\r
303 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
304 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
305 l2cap_cmd_headr=(l2cap_cmd_hdr *)(((uint8_t*)l2cap_headr)+L2CAP_HDR_SIZE);
\r
306 l2cap_conf_response=(l2cap_conf_rsp *)(((uint8_t*)l2cap_cmd_headr)+L2CAP_CMD_HDR_SIZE);
\r
308 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
309 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,(htobs(0x2000)|(bth_connected[dev_num])->handle));
\r
310 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,htobs(L2CAP_CMD_HDR_SIZE+L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
312 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len), htobs(L2CAP_CONF_RSP_SIZE+L2CAP_CMD_HDR_SIZE));
\r
313 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),htobs(0x0001));
\r
315 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____code), L2CAP_CONF_RSP);
\r
316 (bth_connected[dev_num])->ident++;
\r
317 store16(*((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____ident),(bth_connected[dev_num])->ident);
\r
318 store_le16((uint16_t*)((uint8_t*)l2cap_cmd_headr+L2CAP_CMD_HDR____len),htobs(L2CAP_CONF_RSP_SIZE));
\r
320 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____scid),(bth_connected[dev_num])->dcid[pos_chan]);
\r
321 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____flags),0);
\r
322 store_le16((uint16_t*)((uint8_t*)l2cap_conf_response+L2CAP_CONF_RSP____result),0);
\r
323 //posledni polozka jsou data - nebubu posilat v tomto paketu //same as in previous func
\r
326 /******************* umisteni do vysilaciho bufferu **************************/
\r
327 return(l2cap_add_to_send_buffer(bth_r));
\r
331 __bthtomc16((uint8_t*)&(bth_q.scid),((uint8_t*)bth_p+L2CAP_CONF_RSP____scid));
\r
332 __bthtomc16((uint8_t*)&(bth_q.flags),((uint8_t*)bth_p+L2CAP_CONF_RSP____flags));
\r
333 __bthtomc16((uint8_t*)&(bth_q.result),((uint8_t*)bth_p+L2CAP_CONF_RSP____result));
\r
334 return (bth_q.result);;
\r
339 Disconnection request
\r
341 int l2cap_cod_disconn_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x06
\r
347 Disconnection response
\r
349 int l2cap_cod_disconn_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x07
\r
358 int l2cap_cod_echo_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x08
\r
367 int l2cap_cod_echo_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x09
\r
375 int l2cap_cod_info_req(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0a
\r
381 Information request
\r
383 int l2cap_cod_info_rsp(uint8_t *bth_p, uint16_t size, int dev_num, int pos_chan) //0x0b
\r
388 /*----------------------- send data ----------------------------*/
\r
391 * zabali data z dat. zasobniku do peketu a da k odeslani
\r
393 int l2cap_send_data(int inx_handle, int inx_chanal)
\r
396 uint8_t *typ_hci_paket;
\r
397 hci_acl_hdr *hci_headr;
\r
398 l2cap_hdr *l2cap_headr;
\r
402 int hp_size,size=0;
\r
403 uint16_t handle, chanal;
\r
406 if(bth_connected[inx_handle]==NULL) return (-1);
\r
407 if((bth_connected[inx_handle])->dcid[inx_chanal]==0) return (-1);
\r
409 /*reading from sending buffer, try 1 character*/
\r
410 zn=bth_inface_t_isr(0);
\r
413 handle = ((bths_connect_bluet*)bth_connected[inx_handle])->handle;
\r
414 handle=(handle | htobs(0x2000));
\r
415 chanal = (bth_connected[inx_handle])->dcid[inx_chanal];
\r
417 /*make space for the packer + assign adresses for individual parts of L2CAP packet*/
\r
418 hp_size=(HCI_PKT_SIZE+HCI_ACL_HDR_SIZE+L2CAP_HDR_SIZE+BTH_INFACE_BUF_LEN);
\r
419 bth_r=malloc(hp_size);
\r
421 typ_hci_paket=bth_r; //pozice v buff, ktera je prirazena paketu
\r
422 hci_headr=(hci_acl_hdr *)(((uint8_t*)typ_hci_paket)+HCI_PKT_SIZE); //pointer on head
\r
423 l2cap_headr=(l2cap_hdr *)(((uint8_t*)hci_headr)+HCI_ACL_HDR_SIZE); //pointer on parametrs
\r
424 data=((uint8_t*)l2cap_headr+L2CAP_HDR_SIZE); //pointer na data
\r
426 /*-----------------------------DATA FOR SENDING TO PC --------------------------*/
\r
427 *((uint8_t*)data+size)=(uint8_t)zn;
\r
429 /*cyclic reading of the folowing characters and building of the packet*/
\r
430 while ((zn=bth_inface_t_isr(0))>=0)
\r
432 *((uint8_t*)data+size)=(uint8_t)zn;
\r
436 else {return (0);}; //data are not in the queue
\r
438 /*build the rest of the response packet ie. fill the fields*/
\r
439 store16(*typ_hci_paket, HCI_ACLDATA_PKT);
\r
440 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____handle,handle);
\r
441 store_le16((uint8_t*)hci_headr+HCI_ACL_HDR____dlen,(htobs(L2CAP_CMD_HDR_SIZE)+size));
\r
443 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____len),size);
\r
444 store_le16((uint16_t*)((uint8_t*)l2cap_headr+L2CAP_HDR____cid),chanal);
\r
446 // VypisHexa((void*)typ_hci_paket,16);
\r
447 // bth_local_info.busy=0;
\r
448 return(l2cap_add_to_send_buffer(bth_r));
\r