11f504dbdSmatthias.ringwald /* 21f504dbdSmatthias.ringwald * hci.c 31f504dbdSmatthias.ringwald * 41f504dbdSmatthias.ringwald * Created by Matthias Ringwald on 4/29/09. 51f504dbdSmatthias.ringwald * 61f504dbdSmatthias.ringwald */ 71f504dbdSmatthias.ringwald 8475c8125Smatthias.ringwald #include <unistd.h> 993b8dc03Smatthias.ringwald #include <stdarg.h> 1093b8dc03Smatthias.ringwald #include <string.h> 1156fe0872Smatthias.ringwald #include <stdio.h> 121f504dbdSmatthias.ringwald #include "hci.h" 131f504dbdSmatthias.ringwald 14*0a974e0cSmatthias.ringwald // calculate combined ogf/ocf value 15*0a974e0cSmatthias.ringwald #define OPCODE(ogf, ocf) (ocf | ogf << 10) 1693b8dc03Smatthias.ringwald 1793b8dc03Smatthias.ringwald hci_cmd_t hci_inquiry = { 18*0a974e0cSmatthias.ringwald OPCODE(0x01, 0x01), "311" // LAP, Inquiry length, Num_responses 1993b8dc03Smatthias.ringwald }; 2093b8dc03Smatthias.ringwald 2193b8dc03Smatthias.ringwald hci_cmd_t hci_reset = { 22*0a974e0cSmatthias.ringwald OPCODE(0x03, 0x03), "" 2393b8dc03Smatthias.ringwald }; 2493b8dc03Smatthias.ringwald 2593b8dc03Smatthias.ringwald 26475c8125Smatthias.ringwald static hci_transport_t *hci_transport; 27475c8125Smatthias.ringwald 2856fe0872Smatthias.ringwald void hexdump(uint8_t *data, int size){ 2956fe0872Smatthias.ringwald int i; 3056fe0872Smatthias.ringwald for (i=0; i<size;i++){ 3156fe0872Smatthias.ringwald printf("%02X ", data[i]); 3256fe0872Smatthias.ringwald } 3356fe0872Smatthias.ringwald printf("\n"); 3456fe0872Smatthias.ringwald } 3556fe0872Smatthias.ringwald 3656fe0872Smatthias.ringwald #if 0 3756fe0872Smatthias.ringwald static void *hci_daemon_thread(void *arg){ 3856fe0872Smatthias.ringwald printf("HCI Daemon started\n"); 3956fe0872Smatthias.ringwald hci_run(transport, &config); 4056fe0872Smatthias.ringwald return NULL; 4156fe0872Smatthias.ringwald } 4256fe0872Smatthias.ringwald #endif 4356fe0872Smatthias.ringwald 44475c8125Smatthias.ringwald void hci_init(hci_transport_t *transport, void *config){ 45475c8125Smatthias.ringwald 46475c8125Smatthias.ringwald // reference to use transport layer implementation 47475c8125Smatthias.ringwald hci_transport = transport; 48475c8125Smatthias.ringwald 49475c8125Smatthias.ringwald // open unix socket 50475c8125Smatthias.ringwald 51475c8125Smatthias.ringwald // wait for connections 52475c8125Smatthias.ringwald 53475c8125Smatthias.ringwald // enter loop 54475c8125Smatthias.ringwald 55475c8125Smatthias.ringwald // handle events 56475c8125Smatthias.ringwald } 57475c8125Smatthias.ringwald 58475c8125Smatthias.ringwald int hci_power_control(HCI_POWER_MODE power_mode){ 59475c8125Smatthias.ringwald return 0; 60475c8125Smatthias.ringwald } 61475c8125Smatthias.ringwald 6256fe0872Smatthias.ringwald int hci_send_cmd_packet(uint8_t *buffer, int size){ 63475c8125Smatthias.ringwald return hci_transport->send_cmd_packet(buffer, size); 64475c8125Smatthias.ringwald } 65475c8125Smatthias.ringwald 66475c8125Smatthias.ringwald void hci_run(){ 67475c8125Smatthias.ringwald while (1) { 68475c8125Smatthias.ringwald // construct file descriptor set to wait for 69475c8125Smatthias.ringwald // select 70475c8125Smatthias.ringwald 71475c8125Smatthias.ringwald // for each ready file in FD - call handle_data 72475c8125Smatthias.ringwald sleep(1); 73475c8125Smatthias.ringwald } 741f504dbdSmatthias.ringwald } 7593b8dc03Smatthias.ringwald 7693b8dc03Smatthias.ringwald 7793b8dc03Smatthias.ringwald void hci_create_cmd_packet(uint8_t *buffer, uint8_t *cmd_len, hci_cmd_t *cmd, ...){ 78*0a974e0cSmatthias.ringwald buffer[0] = cmd->opcode & 0xff; 79*0a974e0cSmatthias.ringwald buffer[1] = cmd->opcode >> 8; 8093b8dc03Smatthias.ringwald int pos = 3; 8193b8dc03Smatthias.ringwald 8293b8dc03Smatthias.ringwald va_list argptr; 8393b8dc03Smatthias.ringwald va_start(argptr, cmd); 8493b8dc03Smatthias.ringwald const char *format = cmd->format; 8593b8dc03Smatthias.ringwald uint16_t word; 8693b8dc03Smatthias.ringwald uint32_t longword; 8793b8dc03Smatthias.ringwald uint8_t * bt_addr; 8893b8dc03Smatthias.ringwald while (*format) { 8993b8dc03Smatthias.ringwald switch(*format) { 9093b8dc03Smatthias.ringwald case '1': // 8 bit value 9193b8dc03Smatthias.ringwald case '2': // 16 bit value 9293b8dc03Smatthias.ringwald case 'H': // hci_handle 93554588a5Smatthias.ringwald word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 9493b8dc03Smatthias.ringwald buffer[pos++] = word & 0xff; 9593b8dc03Smatthias.ringwald if (*format == '2') { 9693b8dc03Smatthias.ringwald buffer[pos++] = word >> 8; 9793b8dc03Smatthias.ringwald } else if (*format == 'H') { 98554588a5Smatthias.ringwald // TODO 9993b8dc03Smatthias.ringwald } 10093b8dc03Smatthias.ringwald break; 10193b8dc03Smatthias.ringwald case '3': 10293b8dc03Smatthias.ringwald case '4': 10393b8dc03Smatthias.ringwald longword = va_arg(argptr, uint32_t); 10493b8dc03Smatthias.ringwald // longword = va_arg(argptr, int); 10593b8dc03Smatthias.ringwald buffer[pos++] = longword; 10693b8dc03Smatthias.ringwald buffer[pos++] = longword >> 8; 10793b8dc03Smatthias.ringwald buffer[pos++] = longword >> 16; 10893b8dc03Smatthias.ringwald if (*format == '4'){ 10993b8dc03Smatthias.ringwald buffer[pos++] = longword >> 24; 11093b8dc03Smatthias.ringwald } 11193b8dc03Smatthias.ringwald break; 11293b8dc03Smatthias.ringwald case 'B': // bt-addr 11393b8dc03Smatthias.ringwald bt_addr = va_arg(argptr, uint8_t *); 11493b8dc03Smatthias.ringwald memcpy( &buffer[pos], bt_addr, 6); 11593b8dc03Smatthias.ringwald pos += 6; 11693b8dc03Smatthias.ringwald break; 11793b8dc03Smatthias.ringwald default: 11893b8dc03Smatthias.ringwald break; 11993b8dc03Smatthias.ringwald } 12093b8dc03Smatthias.ringwald format++; 12193b8dc03Smatthias.ringwald }; 12293b8dc03Smatthias.ringwald va_end(argptr); 12393b8dc03Smatthias.ringwald buffer[2] = pos - 3; 12493b8dc03Smatthias.ringwald *cmd_len = pos; 12593b8dc03Smatthias.ringwald }