Agora, falando um pouquinho de algo com que eu estou mexendo mais diretamente: MCAP.
O MCAP é um protocolo relativamente novo na pilha Bluetooth, e encaixa-se na camada 5 do modelo OSI (ou seja, é um protocolo de sessão). Numa comparação direta com TCP/IP, ele tem semelhanças com o SCTP e principalmente com o BEEP.
A ideia do MCAP é administrar um conjunto de conexões de transporte L2CAP, que façam parte de uma mesma sessão. Uma conexão MCAP tem exatamente uma conexão L2CAP de controle (denominada MCL) e qualquer número de conexões L2CAP de dados (denominadas MDL).
Além de "enfeixar" conexões que façam parte de uma mesma sessão, o MCAP suporta o conceito de sessão persistente, que sobrevive a eventuais desconexões L2CAP. Uma sessão pode continuar existindo após inúmeras desconexões e reconexões (voluntárias ou involuntárias). A sessão MCAP só deixa de existir quando a aplicação decidir matá-la ou o outro lado reportar que a sessão não é mais conhecida.
O MCAP inclui uma parte opcional que é o CSP (Clock Synchronization Protocol), descrito no post anterior.
Debaixo do capô
Um serviço MCAP ocupa duas "portas" L2CAP: um PSM de controle e outro de dados. O MCAP não prescreve PSMs fixos, eles devem ser dinanicamente alocados, na faixa de PSMs acima de 4096. Se os PSMs mais baixos estiverem livres, um serviço MCAP ficaria ouvindo nos PSMs 4097 e 4099 (apenas os PSMs ímpares podem ser usados no L2CAP0.
Pelo fato dos PSMs não serem fixos, é praticamente obrigatório que um serviço MCAP seja anunciado via SDP, para que "o outro lado" possa descobrir os PSMs. Mas o MCAP não prescreve um formato de registro SDP. Isso fica a cargo do profile de serviço que usa MCAP, como o HDP. O MCAP é apenas um protocolo, e faz pouco sentido usá-lo fora do contexto de um serviço -- ainda menos que RFCOMM e L2CAP, já que não há um número fixo de porta.
Ainda assim, se de alguma forma os PSMs forem conhecidos (ou forem hardcoded no programa), é possível trafegar MCAP sem ter um serviço "de verdade".
É fácil entender o PSM de controle. Cada conexão L2CAP envolvendo o PSM de controle é uma conexão MCAP, existe uma relação de um para um.
Já o PSM de dados é mais enrolado. Cada canal de dados tem um identificador (MDEP ID). Então, por exemplo, se um serviço oferecer cinco canais de dados (imagine um dispositivo com cinco sensores embutidos), o "outro lado" pode conectar apenas os canais de dados desejados. Porém, o PSM de dados é sempre o mesmo.
Se, por exemplo, forem criados cinco canais de dados, o lado que tomou a iniciativa vai conectar cinco vezes no mesmo PSM. Isto cria cinco conexões L2CAP separadas (cada uma com seu próprio CID), cada um correspondente a um MDEP ID diferente.
Ok, e como o MCAP sabe que "aquela" conexão L2CAP corresponde a "aquele" canal de dados? Esta é a parte mais esquisita do MCAP: o atrelamento entre as duas coisas é puramente temporal. A requisição do MDL é feita via canal de controle (MCL), e imediatamente em seguida o requisitante conecta ao PSM de dados. Aí obviamente tem uns timeouts etc.
Isto significa que a requisição de canais de dados tem de ser feita sequencialmente. Requisita, conecta. Deu certo, requisita o próximo e conecta. Não se pode requisitar cinco canais "por atacado" e só depois fazer as conexões L2CAP. É o tipo da coisa que definitivamente dá arrepios em quem está acostumado com TCP/IP...
Se abstraírmos esse mecanismo troncho, em duas fases, de conectar os canais de dados MDL, o MCAP é até interessante. Cada MDEP ID possui um mapa de configuração onde está especificado se o canal solicita ou força algum recurso especial do L2CAP (ERTM, sreaming).
Como é de se esperar, o canal de controle tem um protocolo bem definido. Já os canais de dados não impõem nenhum protocolo. Uma vez aberto o canal, ele é um soquete L2CAP como qualquer outro e a aplicação trafega o que quiser.
O recurso de reconexão do MCAP é opcional; a aplicação pode escolher não utilizar este recurso, e considerar a sessão perdida em caso de desconexão. Por outro lado, se a aplicação quer reconexão, terá de preservar informações de sessão.
Além, disso o MCAP não garante que os canais de dados serão "perfeitos" durante uma sessão. Em caso de desconexão/reconexão, dados "em voo" podem ser perdidos. O protocolo de aplicação precisa implementar algum método de "replay" de requisição, bem como tratar requisições duplicadas.
Isto complica bastante as coisas, e creio que muitas aplicações baseadas em MCAP vão simplesmente optar em não suportar reconexão...
Implementação do MCAP
O MCAP é bastante novo e apenas um perfil, o HDP (também novo) o utiliza. Assim, você não vai encontrar MCAP em nenhum sistema operacional de uso geral por enquanto.
No caso específico do Linux, uma equipe da Espanha, do projeto OpenHealth, tem trabalhado em implementações MCAP e HDP para o BlueZ. O repositório pode ser encontrado em http://gitorious.org/bluez-mcap-hdp.
De minha parte, tenho trabalhado em testes, CSP, bugfixes e definição da API, de modo que MCAP e HDP para BlueZ sejam incorporados ao projeto principal e possuam alta qualidade.
Este trabalho tem atacado em duas frentes. Numa, mantenho um "serviço" ou plug-in BlueZ MCAP que na verdade é apócrifo, pois não está associado a nenhum perfil, e serve mais para brincadeiras/testes. O plug-in foi originalmente escrito pelo pessoal do OpenHealth, e aumentamos seu "poder de fogo" para que seja capaz de exercitar todos os aspectos do MCAP. O repositório é http://gitorious.org/bluez-epx.
A outra linha é uma implementação MCAP e HDP totalmente separada do BlueZ, feita em Python, a que demos o pouco criativo nome de HDPy, cujo repositório é http://gitorious.org/hdpy. Obviamente o HDPy visa ser uma ferramenta de testes, mas nada impede que seja utilizado por aplicativos "sérios" quando estiver mais maduro.
O motivador de criar "ainda outra implementação do MCAP" é fazer com que a implementação principal tenha "com quem conversar", pois os dispositivos Bluetooth que falam MCAP são raros, caros, bugados e não se pode conectar via ssh neles para ver o que está acontecendo. Ter uma implementação totalmente diferente e ainda debugável facilita as coisas.
Como o MCAP é um protocolo de sessão que usa nada além do L2CAP como transporte, é possível implementar MCAP de diversas formas: como uma biblioteca (caso do HDPy), na parte user-level do serviço Bluetooth (caso do OpenHealth) ou mesmo no kernel.
De um ponto de vista "purista", o melhor lugar seria no kernel, pois isto permitiria criar soquetes MCAP, manipuláveis como qualquer outro soquete ou file descriptor, em vez de usar uma API especial. Porém o MCAP é cheio de operações que não cabem na metáfora connect/read/write/close.
E é claro, implementar qualquer coisa dentro do kernel é muito mais difícil de fazer e principalmente de manter (qualquer bug implica que o usuário atualize o kernel, e que o desenvolvedor submeta o conserto no processo de desenvolvimento do Linux).