mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-24 12:40:47 +00:00
unify RFCOMM frame creation
This commit is contained in:
parent
332748b355
commit
8396a0038f
14
TODO.txt
14
TODO.txt
@ -1,14 +1,16 @@
|
|||||||
/* new todo file for BTstack */
|
/* new todo file for BTstack */
|
||||||
|
|
||||||
Last milestone reached: create script to build APT package for BTdeamon, Resources, and BTstack client library
|
Last milestone reached: create script to build APT package for BTdeamon, Resources, and BTstack client library
|
||||||
Last change: added Cocoa CFRunLoop support
|
Last change: don't set name to empty string on error in CocoaTouch
|
||||||
|
|
||||||
NEXT:
|
NEXT:
|
||||||
- CocoaTouch User Interface Components
|
- CocoaTouch User Interface Components
|
||||||
- Inquiry
|
- Show alert when BTstack open fails because of no BTdaemon
|
||||||
- Alerts
|
- Show alert when BTstack init fails because of other stack
|
||||||
|
- define delegate interface for select events
|
||||||
- prepare WiiMoteDemo for release
|
- prepare WiiMoteDemo for release
|
||||||
- add inquiry code
|
- integrate new inquiry code
|
||||||
|
- figure out why stack doesn't shut Bluetooth off when in sleep for a while
|
||||||
- provide test version by setting up APT repository within BTstack SVN
|
- provide test version by setting up APT repository within BTstack SVN
|
||||||
- instructions: http://www.saurik.com/id/7
|
- instructions: http://www.saurik.com/id/7
|
||||||
|
|
||||||
@ -20,10 +22,10 @@ NEXT:
|
|||||||
- commands and events
|
- commands and events
|
||||||
- detect and handle iPhone sleep mode
|
- detect and handle iPhone sleep mode
|
||||||
- see iPhone imnsomnia project at http://code.google.com/p/iphone-insomnia/
|
- see iPhone imnsomnia project at http://code.google.com/p/iphone-insomnia/
|
||||||
- can we get willGoToSleep event, should we should down?
|
- can we get willGoToSleep event, should we turn off Bluetooth?
|
||||||
- would be nice, if we could get woken up by Bluetooth data
|
- would be nice, if we could get woken up by Bluetooth data
|
||||||
- CocoaTouch User Interface Components
|
- CocoaTouch User Interface Components
|
||||||
- Alerts and shutdown of Apple's stack
|
- Warning and shutdown of Apple's stack
|
||||||
- create new GPG key for gmail account and sign APT package
|
- create new GPG key for gmail account and sign APT package
|
||||||
- non-reproducible bug: hci_state gets confused.
|
- non-reproducible bug: hci_state gets confused.
|
||||||
- BlueTool used although hci state should be on (right after quitting example/test)
|
- BlueTool used although hci state should be on (right after quitting example/test)
|
||||||
|
144
example/rfcomm.c
144
example/rfcomm.c
@ -46,49 +46,92 @@
|
|||||||
|
|
||||||
bd_addr_t addr = {0x00,0x1c,0x4d,0x02,0x1a,0x77}; // Zeemote
|
bd_addr_t addr = {0x00,0x1c,0x4d,0x02,0x1a,0x77}; // Zeemote
|
||||||
// bd_addr_t addr = {0x00,0x16,0xcb,0x09,0x94,0xa9}; // sh-mac
|
// bd_addr_t addr = {0x00,0x16,0xcb,0x09,0x94,0xa9}; // sh-mac
|
||||||
// bd_addr_t addr = {0x00,0x0b,0x24,0x37,0xd6,0x80}; // cl800bt
|
// bd_addr_t addr = {0x00,0x0b,0x24,0x37,0xd6,0x80}; // smart card reader
|
||||||
|
// bd_addr_t addr = {0x00,0x80,0x25,0x07,0x2b,0x5f}; // cl800bt
|
||||||
|
|
||||||
#define RFCOMM_CHANNEL_ID 1
|
#define RFCOMM_CHANNEL_ID 1
|
||||||
|
|
||||||
hci_con_handle_t con_handle;
|
hci_con_handle_t con_handle;
|
||||||
uint16_t source_cid;
|
uint16_t source_cid;
|
||||||
|
|
||||||
|
// used to assemble rfcomm packets
|
||||||
|
uint8_t rfcomm_out_buffer[1000];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
|
||||||
|
*/
|
||||||
|
void rfcomm_send_packet(uint16_t source_cid, uint8_t address, uint8_t control, uint8_t credits, uint8_t *data, uint16_t len){
|
||||||
|
|
||||||
|
uint16_t pos = 0;
|
||||||
|
uint8_t crc_fields = 3;
|
||||||
|
|
||||||
|
rfcomm_out_buffer[pos++] = address;
|
||||||
|
rfcomm_out_buffer[pos++] = control;
|
||||||
|
|
||||||
|
// length field can be 1 or 2 octets
|
||||||
|
if (len < 128){
|
||||||
|
rfcomm_out_buffer[pos++] = (len << 1)| 1; // bits 0-6
|
||||||
|
} else {
|
||||||
|
rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
|
||||||
|
rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14
|
||||||
|
crc_fields++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add credits for UIH frames when PF bit is set
|
||||||
|
if (control == BT_RFCOMM_UIH_PF){
|
||||||
|
rfcomm_out_buffer[pos++] = credits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy actual data
|
||||||
|
memcpy(&rfcomm_out_buffer[pos], data, len);
|
||||||
|
pos += len;
|
||||||
|
|
||||||
|
// UIH frames only calc FCS over address + control (5.1.1)
|
||||||
|
if ((control & 0xef) == BT_RFCOMM_UIH){
|
||||||
|
crc_fields = 2;
|
||||||
|
}
|
||||||
|
rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
|
||||||
|
bt_send_l2cap( source_cid, rfcomm_out_buffer, pos);
|
||||||
|
}
|
||||||
|
|
||||||
void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t channel)
|
void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t channel)
|
||||||
{
|
{
|
||||||
uint8_t payload[4];
|
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
||||||
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_SABM, 0, NULL, 0);
|
||||||
payload[1] = BT_RFCOMM_SABM; // control field
|
|
||||||
payload[2] = (0 << 2) | 1; // set EA bit to 1 to indicate 7 bit length field
|
|
||||||
payload[3] = crc8_calc(payload, 3); // calc fcs
|
|
||||||
bt_send_l2cap( source_cid, payload, sizeof(payload));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t signals)
|
void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t signals)
|
||||||
{
|
{
|
||||||
uint8_t payload[8];
|
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
||||||
|
uint8_t payload[4];
|
||||||
// This is a command
|
uint8_t pos = 0;
|
||||||
payload[0] = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
payload[pos++] = BT_RFCOMM_MSC_CMD;
|
||||||
payload[1] = BT_RFCOMM_UIH; // control field
|
payload[pos++] = 2 << 1 | 1; // len
|
||||||
payload[2] = 4 << 1 | 1; // len
|
payload[pos++] = (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3); // shouldn't D = initiator = 1 ?
|
||||||
|
payload[pos++] = signals;
|
||||||
payload[3] = BT_RFCOMM_MSC_CMD;
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
||||||
payload[4] = 2 << 1 | 1; // len
|
|
||||||
payload[5] = (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3); // shouldn't D = initiator = 1 ?
|
|
||||||
payload[6] = signals;
|
|
||||||
|
|
||||||
payload[7] = crc8_calc(payload, 2); // calc fcs, 3 bytes to be send...
|
|
||||||
bt_send_l2cap( source_cid, payload, sizeof(payload));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
|
void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
|
||||||
uint8_t payload[len+4];
|
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
||||||
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, data, len);
|
||||||
payload[1] = BT_RFCOMM_UIH; // control field
|
}
|
||||||
payload[2] = (len<<1) | 1; // len
|
|
||||||
memcpy(&payload[3], data, len);
|
void _bt_rfcomm_send_uih_pn_command(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint16_t max_frame_size){
|
||||||
payload[3+len] = crc8_calc(payload, 2); // calc fcs
|
uint8_t payload[10];
|
||||||
bt_send_l2cap( source_cid, payload, sizeof(payload));
|
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
||||||
|
uint8_t pos = 0;
|
||||||
|
payload[pos++] = BT_RFCOMM_PN_CMD;
|
||||||
|
payload[pos++] = 8 << 1 | 1; // len
|
||||||
|
payload[pos++] = channel << 1;
|
||||||
|
payload[pos++] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
|
||||||
|
payload[pos++] = 0; // priority
|
||||||
|
payload[pos++] = 0; // max 60 seconds ack
|
||||||
|
payload[pos++] = max_frame_size & 0xff; // max framesize low
|
||||||
|
payload[pos++] = max_frame_size >> 8; // max framesize high
|
||||||
|
payload[pos++] = 0x00; // number of retransmissions
|
||||||
|
payload[pos++] = 0x00; // unused error recovery window
|
||||||
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||||
@ -104,36 +147,13 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
|||||||
case L2CAP_DATA_PACKET:
|
case L2CAP_DATA_PACKET:
|
||||||
// rfcomm: data[8] = addr
|
// rfcomm: data[8] = addr
|
||||||
// rfcomm: data[9] = command
|
// rfcomm: data[9] = command
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
// received 1. message BT_RF_COMM_UA
|
// received 1. message BT_RF_COMM_UA
|
||||||
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == 0x03){
|
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == 0x03){
|
||||||
packet_processed++;
|
packet_processed++;
|
||||||
printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
|
printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
|
||||||
printf("Sending UIH Parameter Negotiation Command\n");
|
printf("Sending UIH Parameter Negotiation Command\n");
|
||||||
// _bt_rfcomm_send_sabm(source_cid, 1, 1);
|
_bt_rfcomm_send_uih_pn_command(source_cid, 1, RFCOMM_CHANNEL_ID, 100);
|
||||||
uint8_t payload[14];
|
|
||||||
uint8_t initiator = 1;
|
|
||||||
uint8_t channel = RFCOMM_CHANNEL_ID;
|
|
||||||
payload[0] = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
|
||||||
payload[1] = BT_RFCOMM_UIH; // control field
|
|
||||||
payload[2] = 10 << 1 | 1; // len
|
|
||||||
|
|
||||||
payload[3] = BT_RFCOMM_PN_CMD;
|
|
||||||
payload[4] = 8 << 1 | 1; // len
|
|
||||||
|
|
||||||
payload[5] = channel << 1;
|
|
||||||
payload[6] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
|
|
||||||
payload[7] = 0; // priority
|
|
||||||
payload[8] = 0; // max 60 seconds ack
|
|
||||||
payload[9] = 0x96; // max framesize low
|
|
||||||
payload[10] = 0x06; // max framesize high
|
|
||||||
payload[11] = 0x00; // number of retransmissions
|
|
||||||
payload[12] = 0x00; // unused error recovery window
|
|
||||||
|
|
||||||
payload[13] = crc8_calc(payload, 2 ); // calc fcs, 3 bytes to be send...
|
|
||||||
bt_send_l2cap( source_cid, payload, sizeof(payload));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// received UIH Parameter Negotiation Response
|
// received UIH Parameter Negotiation Response
|
||||||
@ -144,7 +164,6 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
|||||||
_bt_rfcomm_send_sabm(source_cid, 1, 1);
|
_bt_rfcomm_send_sabm(source_cid, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// received 2. message BT_RF_COMM_UA
|
// received 2. message BT_RF_COMM_UA
|
||||||
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == ((RFCOMM_CHANNEL_ID << 3) | 3) ){
|
if (size == 12 && packet[9] == BT_RFCOMM_UA && packet[8] == ((RFCOMM_CHANNEL_ID << 3) | 3) ){
|
||||||
packet_processed++;
|
packet_processed++;
|
||||||
@ -160,11 +179,9 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
|||||||
printf("Responding to 'I'm ready'\n");
|
printf("Responding to 'I'm ready'\n");
|
||||||
// fine with this
|
// fine with this
|
||||||
uint8_t * payload = &packet[8];
|
uint8_t * payload = &packet[8];
|
||||||
payload[0] |= 2; // response
|
uint8_t address = payload[0] | 2; // set response
|
||||||
payload[3] = BT_RFCOMM_MSC_RSP;
|
payload[3] = BT_RFCOMM_MSC_RSP; // " "
|
||||||
payload[7] = crc8_calc(payload, 2);
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, 0x30, payload, 8);
|
||||||
bt_send_l2cap( source_cid, payload, 8);
|
|
||||||
//
|
|
||||||
msc_resp_send = 1;
|
msc_resp_send = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,15 +218,10 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (send_credits_packet) {
|
if (send_credits_packet) {
|
||||||
|
// send 0x30 credits
|
||||||
uint8_t initiator = 1;
|
uint8_t initiator = 1;
|
||||||
uint8_t channel = RFCOMM_CHANNEL_ID;
|
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (RFCOMM_CHANNEL_ID << 3);
|
||||||
uint8_t payload[5];
|
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, 0x30, NULL, 0);
|
||||||
payload[0] = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
|
||||||
payload[1] = BT_RFCOMM_UIH_PF; // control field
|
|
||||||
payload[2] = (0<<1) | 1; // len
|
|
||||||
payload[3] = 0x30; // credits
|
|
||||||
payload[4] = crc8_calc(payload, 2); // calc fcs
|
|
||||||
bt_send_l2cap( source_cid, payload, sizeof(payload));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packet_processed){
|
if (!packet_processed){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user