Seite 1 von 1

Bluetooth ..und wie es weiter geht :)

Verfasst: 23.11.2019 16:34
von ccode_new
Hallo!

Alles hat einen Anfang und mehrere Tiefen und Höhen.

Ich möchte etwas tiefer in das Thema "Bluetooth" eintauchen.
Dies möchte ich auch erstmal nur auf Linux beschränken und später vlt. auf andere OS (Windows, Mac) erweitern.

Man kann unter Linux sehr gut mit Kommandozeilen-Befehlen (mit kleinen Hilfsprogrammen) arbeiten.

Zum Beispiel kann man nach dem Wissen der Bluetooth-Adresse eine Kommunikation mit rfcomm (oder über die PureBasic - SerialPort -Bibliothek) sehr gut erledigen.

Auch kann man sehr gut mit "obexftp" Dateien an z.B. ein Smartphone senden und auch Dateien wieder empfangen.

Das geht alles mit kleinen Hilfprogrammen (hcitool, bt-obex, bt-adapter, ...) sehr gut, aber schöner wäre es diesen Weg zu umgehen.
Dies bedeutet aber auch sich tiefer mit der bluez-lib zu beschäftigen und auch mit der Programmiersprache C und den Übersetzen von Header-Dateien.)

Hat sich damit schon mal jemand anderes hier näher beschäftigt ?

Ziel: Eine Verbindung (Server/Client) mit OBEX zur Dateiübermittlung über Bluetooth per API.

Danke!

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 23.11.2019 17:43
von NicTheQuick
Leider noch nicht. Fänd ich aber auch interessant. Mit rfcomm und serieller Schnittstelle hab ich auch schon öfter was gemacht. Mehr war aber auch nicht nötig bisher.

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 23.11.2019 20:19
von ccode_new
Hi Nic!

Interessant ist es, aber auch recht knifflig.

Am einfachsten ist eben die kompilierten Hilfprogramme von "bluez-tools-master" zu nutzen, aber ich Suche ja nach einer API-Lösung.

Dabei würde ich aber eigentlich auch gerne soviel wie möglich zusätzlicher Abhängigkeiten vermeiden.
(readline-dev, etc.)

Wenn ich mir jetzt die "bt-obex.c" -Datei so betrachte möchte ich aber eigentlich auch gerne auf das Ganze Glib2.0 /Gio - Zeug verzichten.

Anbei:
Gibt es eine einfachere Möglichkeit mit den Standards (hci/sdp/rfcomm) eine Dateiübertragung hinzubekommen.

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 24.11.2019 18:51
von ccode_new
Ich habe hier mal eine Frage:

Wie kann ich das hier in PureBasic umsetzen ?

#define __UUID_FBS_bytes \
{ 0xF9, 0xEC, 0x7B, 0xC4, \
0x95, 0x3C, 0x11, 0xD2, 0x98, 0x4E, \
0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 }

#define UUID_FBS ((const uint8_t []) __UUID_FBS_bytes)

(Definiert in: obexftp/uuid.h)

Und wie deklariere ich diese Funktion richtig in PureBasic ?:
int obexftp_connect_src (obexftp_client_t *cli, const char *src, const char *device, int port, const uint8_t uuid[], uint32_t uuid_len)
Connect this ObexFTP client using a given source address by sending an OBEX CONNECT request.
Es geht hier um die Array-Übergabe an die Funktion.

Danke!

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 24.11.2019 20:07
von ccode_new
:mrgreen:

Also hiermit funktioniert zumindest schon mal das Senden mit OBEX über Bluetooth:

Code: Alles auswählen

;Benötigt Linux und die "libbluetooth-dev" und die "libobexftp-dev" (BlueZ)

Structure bdaddr_t
  blupp.b[6]
EndStructure

Structure inquiry_info
  bdaddr.bdaddr_t
  pscan_rep_mode.b
  pscan_period_mode.b
  pscan_mode.b
  dev_class.b[3]
  clock_offset.w
EndStructure

#INQUIRY_INFO_SIZE = SizeOf(inquiry_info) ;14

Enumeration
  #OBEXFTP_EV_ERRMSG 	
  #OBEXFTP_EV_OK 	
  #OBEXFTP_EV_ERR 	
  #OBEXFTP_EV_CONNECTING 	
  #OBEXFTP_EV_DISCONNECTING 	
  #OBEXFTP_EV_SENDING 	
  #OBEXFTP_EV_LISTENING 	
  #OBEXFTP_EV_CONNECTIND 	
  #OBEXFTP_EV_DISCONNECTIND 	
  #OBEXFTP_EV_RECEIVING 	
  #OBEXFTP_EV_BODY 	
  #OBEXFTP_EV_INFO 	
  #OBEXFTP_EV_PROGRESS 
EndEnumeration

#OBEX_TRANS_IRDA = 1
#OBEX_TRANS_INET = 2
#OBEX_TRANS_CUST = 3
#OBEX_TRANS_CUSTOM = 3
#OBEX_TRANS_BLUETOOTH = 4
#OBEX_TRANS_FD = 5
#OBEX_TRANS_USB = 6

#OBEXFTP_LEADING_SLASH = $01
#OBEXFTP_TRAILING_SLASH = $02
#OBEXFTP_SPLIT_SETPATH = $04
#OBEX_CONN_HEADER = $08

Structure stat_entry_t
  name.b[256]
  mode.l ;mode_t (4 Byte)
  size.l
  mtime.i ;time_t (8 Byte)
EndStructure

Structure cache_object
  *nex
  refcnt.l
  timestamp.i ;time_t
  size.l
  *name ;char *
  *content ;char *
  stats.stat_entry_t
EndStructure

Structure obexftp_info_cb_t
  event.l
  *buf
  len.l
  *datas
EndStructure

Structure obexftp_client_t
  *obexhandle
  connection_id.l
  *ctrans
  transport.l
  finished.l
  success.l
  obex_rsp.l
  mutex.l
  quirks.l
  infocb.obexftp_info_cb_t
  *infocb_data
  fd.l
  stream_chunk.b
  out_size.l
  out_pos.l
  out_data.b
  *target_fn
  buf_size.l
  buf_data.b
  apparam_info.l
  *cache.cache_object_t
  cache_timeout.l
  cache_maxsize.l
EndStructure

#DEFAULT_CACHE_TIMEOUT = 180
#DEFAULT_CACHE_MAXSIZE = 10240
#OBEX_SYNC_SERVICE = $1104
#OBEX_PUSH_SERVICE = $1105
#OBEX_FTP_SERVICE = $1106

; #define __UUID_FBS_bytes \
; { 0xF9, 0xEC, 0x7B, 0xC4, \
;   0x95, 0x3C, 0x11, 0xD2, 0x98, 0x4E, \
;   0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 }
; 
; #define UUID_FBS ((const uint8_t []) __UUID_FBS_bytes)
Global Dim UUID_FBS.b(15)
UUID_FBS(0) = $F9 : UUID_FBS(1) = $EC : UUID_FBS(2) = $7B : UUID_FBS(3) = $C4
UUID_FBS(4) = $95 : UUID_FBS(5) = $3C : UUID_FBS(6) = $11 : UUID_FBS(7) = $D2
UUID_FBS(8) = $98 : UUID_FBS(9) = $4E : UUID_FBS(10) = $52 : UUID_FBS(11) = $54
UUID_FBS(12) = $00 : UUID_FBS(13) = $DC : UUID_FBS(14) = $9E : UUID_FBS(15) = $09


Import "-lbluetooth"
  hci_get_route.i( *bdaddr.bdaddr_t )
  hci_open_dev.i( dev_id.i )
  hci_inquiry.i( dev_id.i, len.i, num_rsp.i, *lap, *ii.bdaddr_t, flags.l )
  hci_read_remote_name.i( dd.i, *bdaddr.bdaddr_t, len.i, *name.p-utf8, gTo.i )
  
  ba2str.i(*ba.bdaddr_t, *str)
EndImport

Import "-lobexftp"
  obexftp_open.i(transport.l, *ctrans, *infocb.obexftp_info_cb_t, *infocb_data )
  obexftp_close(*cli.obexftp_client_t)
  obexftp_discover.i(transport.l)
  obexftp_discover_bt_src.i(*src)
  obexftp_browse_bt_src.i(*src, *addr, svclass.l)
  obexftp_connect_uuid.i(*cli.obexftp_client_t, *device, port.l, uuid.i, uuid_len.l)
  obexftp_connect_src.i(*cli.obexftp_client_t, *src, *device, port.l, uuid.i, uuid_len.l)
  obexftp_disconnect.i(*cli.obexftp_client_t)
  obexftp_setpath.i(*cli.obexftp_client_t, *name, create.l)
  obexftp_get_type.i(*cli.obexftp_client_t, *type, *localname.p-utf8, *remotename.p-utf8)
  obexftp_put_file.i(*cli.obexftp_client_t, *filename.p-utf8, *remotename.p-utf8)
  obexftp_put_data.i(*cli.obexftp_client_t, *datas, size.l, *remotename.p-utf8)
  obexftp_del.i(*cli.obexftp_client_t, *name.p-utf8)
  obexftp_info.i(*cli.obexftp_client_t, opcode.b)
  obexftp_rename.i(*cli.obexftp_client_t, *sourcename.p-utf8, *targetname.p-utf8)
  obexftp_opendir(*cli.obexftp_client_t, *name.p-utf8)
  obexftp_closedir.i(*dir)
  obexftp_readdir.i(*dir)
  obexftp_stat.i(*cli.obexftp_client_t, *name.p-utf8)
EndImport


Procedure.s Bluetooth_Scan(ret_addr.i) ;ret_addr = Rückgabe der gefundenen BT-Adresse (0 = erste Adresse, 1 = zweite Adresse, usw.)
  Protected ii.inquiry_info
  Protected max_rsp.i, num_rsp.i
  Protected dev_id.i, sock.i, len.i, flags.i
  Protected i
  Protected addr.s{19}
  Protected name.s{248}
  
  dev_id = hci_get_route(0)
  sock = hci_open_dev(dev_id)
  
  If dev_id < 0 Or sock < 0
    MessageRequester("Error", "Verbindung zum Socket fehlgeschlagen.")
  Else
    MessageRequester("Info", "Verbindung zum Socket hergestellt."+#LFCR$+ "Bitte warten Sie einen Moment"+#CRLF$+"Es wird nach BT-Geräten gesucht.")
    
    len = 8
    max_rsp = 255
    flags = 0
    
    kk = AllocateMemory(max_rsp * #INQUIRY_INFO_SIZE)
    
    num_rsp = hci_inquiry(dev_id, len, max_rsp, 0, @kk, flags) ;Anfrage

    If num_rsp < 0
      MessageRequester("Error", "Ein Fehler ist aufgetreten.")
    Else
      For i = 0 To num_rsp -1
        ba2str(kk + (#INQUIRY_INFO_SIZE * i), @addr)
        Debug PeekS(@addr, #PB_Any, #PB_UTF8)
        hci_read_remote_name(sock, kk + (#INQUIRY_INFO_SIZE * i), SizeOf(name), @name, 0)
        Debug PeekS(@name, #PB_Any, #PB_UTF8)
        If ret_addr = i
          FreeMemory(kk)
          ProcedureReturn PeekS(@addr, #PB_Any, #PB_UTF8)
        EndIf
      Next i  
    EndIf
    FreeMemory(kk)
  EndIf
  ProcedureReturn "0"
EndProcedure

Procedure Bluetooth_Send(btaddr.s, file.s)
  Protected channel.i = -1
  Protected *cli.obexftp_client_t = #Null
  Protected ret.i
  
  If btaddr <> ""
    channel = obexftp_browse_bt_src(#Null, Ascii(btaddr), #OBEX_PUSH_SERVICE)
    ;Open Connection
    *cli = obexftp_open(#OBEX_TRANS_BLUETOOTH, #Null, #Null, #Null)
    If *cli <> #Null
      ret = obexftp_connect_uuid(*cli, Ascii(btaddr), channel, #Null, 0)
      If ret > 0
        ;Push file
        ret = obexftp_put_file(*cli, UTF8(file), UTF8(GetFilePart(file)))
        ;Disconnect
        ret = obexftp_disconnect(*cli)
        ;Close
        obexftp_close(*cli)
        *cli = #Null
      EndIf
    Else
      MessageRequester("Error", "Error opening obexftp client")
    EndIf
  EndIf
  
EndProcedure

;-Main
Global SendFile.s = ""
Global baddr.s = ""

baddr = Bluetooth_Scan(0)

If baddr <> "0"
  SendFile = OpenFileRequester("Dateiauswahl", "", "*.", 0)
  Bluetooth_Send(baddr, SendFile)
EndIf

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 24.11.2019 21:56
von ccode_new
Wie kann ich das hier:

ioctl(ctl, HCISETSCAN, (unsigned long) &dr)

in PureBasic umsetzen?

#define HCISETSCAN _IOW('H', 221, int)


Das würde ich brauchen um den Server (Bluetooth-Adaper) entdeckbar zu machen.

Auch brauche ich noch eine verlässliche Möglichkeit um per API einen Client als "Trusted" zu schalten.

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 25.11.2019 20:48
von ccode_new
Oha!

Ich bin (noch) zu doof um die "#include <sys/ioctl.h>" mit den dortigen Macro-Definitionen in Bezug auf direkte Kernel-Funktion zu verstehen.

Daher habe ich die ioctl - Aufrufe mal über einer kleinen kompilierten .so -Datei gemacht.
Damit kann ich diese Aufrufe dann auch über PureBasic nutzen.

Aber irgendwie muss es doch auch eine einfachere Api-Möglichkeit geben um den localen BT-Adapter von Unsichtbar auf Sichtbar zu schalten.
Aus der hci_lib bin ich dahingehend aber noch nicht schlau gewurden.

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 26.11.2019 19:37
von ccode_new
Bald nun ist Weihnachtszeit...

Hallo!

Ich habe mich jetzt an der Funktion ioctl() festgebissen.

Auch wenn es unter PureBasic wahrscheinlich fast aussichtlos ist diese Funktion zum laufen zu bringen.

Ist der interne PureBasic-Aufruf: ioctl_()
überhaubt richtig definiert ?
Wenn dem nicht so ist kann ich es eigentlich gleich aufgeben, aber ich gebe die Hoffnung noch nicht auf.

Wie nimmt PureBasic dort intern signed / unsigned - INT - Typen entgegen ?

Dies ist jetzt meine Definition von <sys/ioctl.h> :

Code: Alles auswählen

#_IOC_NRBITS = 8
#_IOC_TYPEBITS = 8
#_IOC_SIZEBITS = 14
#_IOC_DIRBITS	= 2

#_IOC_NRMASK = ((1 << #_IOC_NRBITS)-1)
#_IOC_TYPEMASK = ((1 << #_IOC_TYPEBITS)-1)
#_IOC_SIZEMASK = ((1 << #_IOC_SIZEBITS)-1)
#_IOC_DIRMASK	= ((1 << #_IOC_DIRBITS)-1)
 
#_IOC_NRSHIFT	= 0
#_IOC_TYPESHIFT	= (#_IOC_NRSHIFT+#_IOC_NRBITS)
#_IOC_SIZESHIFT	= (#_IOC_TYPESHIFT+#_IOC_TYPEBITS)
#_IOC_DIRSHIFT	= (#_IOC_SIZESHIFT+#_IOC_SIZEBITS)

#_IOC_NONE = 0; unsigned long ?
#_IOC_WRITE	= 1; unsigned long ?
#_IOC_READ = 2; unsigned long ?

Macro _IOC(dir,type,nr,size)
  (((dir)  << #_IOC_DIRSHIFT) | ((type) << #_IOC_TYPESHIFT) | ((nr)   << #_IOC_NRSHIFT) | ((size) << #_IOC_SIZESHIFT))
EndMacro

Macro _IOC_TYPECHECK(t) 
  (SizeOf(t))
EndMacro

Macro _IO(type,nr)
  _IOC(#_IOC_NONE,(type),(nr),0)
EndMacro

Macro _IOR(type,nr,size)
  _IOC(#_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOW(type,nr,size)
  _IOC(#_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOWR(type,nr,size)
  _IOC(#_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOR_BAD(type,nr,size)
  _IOC(#_IOC_READ,(type),(nr),SizeOf(size))
EndMacro

Macro _IOW_BAD(type,nr,size)
  _IOC(#_IOC_WRITE,(type),(nr),SizeOf(size))
EndMacro

Macro _IOWR_BAD(type,nr,size)
  _IOC(#_IOC_READ|#_IOC_WRITE,(type),(nr),SizeOf(size))
EndMacro

Structure int
  val.l
EndStructure

Structure uint ;?
  v1.u
  v2.u
EndStructure

#HCISETSCAN  = _IOW('H', 221, int)
Wie kann ich dort so etwas definieren ?:

#define _IOC_WRITE 1U

Diesen Aufruf mache ich dann über PureBasic / oder C mit SUDO-Rechten:

Code: Alles auswählen

  Protected dr.hci_dev_req
  
  dev_id = hci_get_route(0)
  sock = hci_open_dev(dev_id)
  
  dr\dev_id  = dev_id
  ;dr\dev_opt = #SCAN_DISABLED
  dr\dev_opt = #SCAN_PAGE|#SCAN_INQUIRY

  If ioctl_(sock, #HCISETSCAN, @dr) < 0 ;Wie bekomme ich einen 4 Byte großen unsigned long Zeiger ?
    End
  EndIf
Das geht aber so absolut nicht!

Unter C ist das so ausgeführt:

Code: Alles auswählen

static void cmd_scan(int ctl, int hdev, char *opt)
{
	struct hci_dev_req dr;

	dr.dev_id  = hdev;
	dr.dev_opt = SCAN_DISABLED;
	if (!strcmp(opt, "iscan"))
		dr.dev_opt = SCAN_INQUIRY;
	else if (!strcmp(opt, "pscan"))
		dr.dev_opt = SCAN_PAGE;
	else if (!strcmp(opt, "piscan"))
		dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY;

	if (ioctl(ctl, HCISETSCAN, (unsigned long) &dr) < 0) {
		fprintf(stderr, "Can't set scan mode on hci%d: %s (%d)\n",
						hdev, strerror(errno), errno);
		exit(1);
	}
}
Mit SUDO-Rechten klappt das unter C, aber wie bekomme ich das unter PureBasic hin ?

Danke!

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 26.11.2019 22:14
von NicTheQuick
Hast du denn das Purebasic-Programm auch mit root-Rechten gestartet?

Abgesehen davon glaube ich, dass "unsigned long" tatsächlich 64 Bit sind und keine 32. Aber das machst du ja auch richtig, nur der Kommentar dahinter mit den 4 Bytes irritiert etwas.

Könntest du mir einen kleinen Beispielcode machen, der alles enthält, was ich brauche um ioctl_() aufzurufen? Momentan fehlt mir z.B. die Struktur "hci_dev_req".

Re: Bluetooth ..und wie es weiter geht :)

Verfasst: 27.11.2019 18:26
von ccode_new
So passt es erstmal: (Hier gilt die 4 + 2 = 8 Regel ;) )

Code: Alles auswählen

;Host_Controller_Interface_Test_Code ;)

;Linux rockt!
;Bluetooth Power On!

;Anleitung:
;Bitte als Binary kompilieren und mit SUDO-Rechten starten.
;Bitte nicht verarschen lassen.
;Die ioctl - Funktion gibt zwar einen zulässigen Wert zurück, aber dieser sollte hier FALSCH sein.
;Bitte wirklich nachprüfen ob es geklappt hat.

#_IOC_NRBITS = 8
#_IOC_TYPEBITS = 8
#_IOC_SIZEBITS = 14
#_IOC_DIRBITS	= 2

#_IOC_NRMASK = ((1 << #_IOC_NRBITS)-1)
#_IOC_TYPEMASK = ((1 << #_IOC_TYPEBITS)-1)
#_IOC_SIZEMASK = ((1 << #_IOC_SIZEBITS)-1)
#_IOC_DIRMASK	= ((1 << #_IOC_DIRBITS)-1)

#_IOC_NRSHIFT	= 0
#_IOC_TYPESHIFT	= (#_IOC_NRSHIFT+#_IOC_NRBITS)
#_IOC_SIZESHIFT	= (#_IOC_TYPESHIFT+#_IOC_TYPEBITS)
#_IOC_DIRSHIFT	= (#_IOC_SIZESHIFT+#_IOC_SIZEBITS)

#_IOC_NONE = 0 & $FF ; unsigned long ?
#_IOC_WRITE	= 1 & $FF; unsigned long ?
#_IOC_READ = 2 & $FF ; unsigned long ?


Macro _IOC(dir,type,nr,size)
  (((dir)  << #_IOC_DIRSHIFT) | ((type) << #_IOC_TYPESHIFT) | ((nr)   << #_IOC_NRSHIFT) | ((size) << #_IOC_SIZESHIFT))
EndMacro

Macro _IOC_TYPECHECK(t) 
  (SizeOf(t))
EndMacro

Macro _IO(type,nr)
  _IOC(#_IOC_NONE,(type),(nr),0)
EndMacro

Macro _IOR(type,nr,size)
  _IOC(#_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOW(type,nr,size)
  _IOC(#_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOWR(type,nr,size)
  _IOC(#_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
EndMacro

Macro _IOR_BAD(type,nr,size)
  _IOC(#_IOC_READ,(type),(nr),SizeOf(size))
EndMacro

Macro _IOW_BAD(type,nr,size)
  _IOC(#_IOC_WRITE,(type),(nr),SizeOf(size))
EndMacro

Macro _IOWR_BAD(type,nr,size)
  _IOC(#_IOC_READ|#_IOC_WRITE,(type),(nr),SizeOf(size))
EndMacro

Structure int
  val.l
EndStructure

Structure uint
  v1.u
  v2.u
EndStructure

Structure ulong
  v1.u
  v2.u
  v3.u
  v4.u
EndStructure

#HCISETSCAN  = _IOW('H', 221, int)

Structure bdaddr_t
  blupp.b[6]
EndStructure

Structure hci_version
  manufacturer.w
  hci_ver.b
  hci_rev.w
  lmp_ver.b
  lmp_subver.w
EndStructure

Structure hci_request
  ogf.w
  ocf.w
  event.i
  *cparam
  clen.i
  *rparam
  rlen.i
EndStructure

;Ioctl requests structures
Structure hci_dev_stats
  err_rx.l
  err_tx.l
  cmd_tx.l
  evt_rx.l
  acl_tx.l
  acl_rx.l
  sco_tx.l
  sco_rx.l
  byte_rx.l
  byte_tx.l
EndStructure

Structure hci_dev_info
  dev_id.w
  name.c[8]
  
  bdaddr.bdaddr_t
  
  flags.l
  type.b
  
  features.b[8]
  
  pkt_type.l
  link_policy.l
  link_mode.l
  
  acl_mtu.w
  acl_pkts.w
  sco_mtu.w
  sco_pkts.w
  
  stat.hci_dev_stats
EndStructure

Structure hci_conn_info
  handle.w
  bdaddr.bdaddr_t  
  type.b
  out.b
  state.w
  link_mode.l
EndStructure

; struct hci_dev_req { alignment ?
; 	uint16_t dev_id;
; 	uint32_t dev_opt;
; };

Structure hci_dev_req ;So geht es!
  dev_id.l
  dev_opt.l
EndStructure

Structure hci_dev_list_req
  dev_num.w
  dev_req.hci_dev_req[0]
EndStructure

Structure hci_conn_list_req
  dev_id.w
  conn_num.w
  conn_info.hci_conn_info[0]
EndStructure

Structure hci_conn_info_req
  bdaddr.bdaddr_t
  type.b
  conn_info.hci_conn_info[0]
EndStructure

Structure hci_auth_info_req
  bdaddr.bdaddr_t
  type.b
EndStructure

Structure hci_inquiry_req
  dev_id.w
  flags.w
  lap.b[3]
  length.b
  num_rsp.b
EndStructure
#IREQ_CACHE_FLUSH = $0001

Structure inquiry_info
  bdaddr.bdaddr_t
  pscan_rep_mode.b
  pscan_period_mode.b
  pscan_mode.b
  dev_class.b[3]
  clock_offset.w
EndStructure

#INQUIRY_INFO_SIZE = SizeOf(inquiry_info) ;14

#SCAN_DISABLED = $00
#SCAN_INQUIRY = $01
#SCAN_PAGE = $02

Import "-lbluetooth"
  hci_open_dev.i( dev_id.i )
  hci_close_dev.i( dd.i )
  hci_send_cmd.i( dd.i, ogf.w, ocf.w, plen.b, *param )
  hci_send_req.i( dd.i, *req.hci_request, timeout.i )
  
  hci_create_connection.i( dd.i, *bdaddr.bdaddr_t, ptype.w, clkoffset.w, rswitch.b, *handle, gto.i )
  hci_disconnect.i( dd.i, handle.w, reason.b, gto.i )
  
  hci_inquiry.i( dev_id.i, len.i, num_rsp.i, *lap, *ii.bdaddr_t, flags.l )
  hci_devinfo.i( dev_id.i, *di.hci_dev_info )
  hci_devba.i( dev_id.i, *bdaddr.bdaddr_t )
  hci_devid.i( *str )
  
  hci_read_local_name.i( dd.i, len.i, *name.p-utf8, gto.i )
  hci_write_local_name.i( dd.i, *name.p-utf8, gto.i )
  hci_read_remote_name.i( dd.i, *bdaddr.bdaddr_t, len.i, *name.p-utf8, gto.i )
  hci_read_remote_name_with_clock_offset.i( dd.i, *bdaddr.bdaddr_t, pscan_rep_mode.b, clkoffset.w, len.i, *name.p-utf8, gto.i )
  hci_read_remote_name_cancel.i( dd.i, *bdaddr.bdaddr_t, gto.i )
  hci_read_remote_version.i( dd.i, handle.w, *ver.hci_version, gto.i )
  
  hci_read_remote_features.i( dd.i, handle.w, *features, gto.i )
  hci_read_remote_ext_features.i( dd.i, handle.w, page.b, *max_page, *features, gto.i )
  hci_read_clock_offset.i( dd.i, handle.w, *clkoffset, gto.i )
  hci_read_local_version.i( dd.i, *ver.hci_version, gto.i )
  hci_read_local_commands.i( dd.i, *commands, gto.i )
  hci_read_local_features.i( dd.i, *features, gto.i )
  hci_read_local_ext_features.i( dd.i, page.b, *max_page, *features, gto.i )
  hci_read_bd_addr.i( dd.i, *bdaddr.bdaddr_t, gto.i)
  hci_read_class_of_dev.i( dd.i, *cls, gto.i )
  hci_write_class_of_dev.i( dd.i, cls.l, gto.i )
  hci_read_voice_setting.i( dd.i, *vs, gto.i )
  hci_write_voice_setting.i( dd.i, vs.w, gto.i )
  hci_read_current_iac_lap.i( dd.i, *num_iac, *lap, gto.i )
  hci_write_current_iac_lap.i( dd.i, num_iac.b, *lap, gto.i )
  hci_read_stored_link_key.i( dd.i, *bdaddr.bdaddr_t, all.b, gto.i )
  hci_write_stored_link_key.i( dd.i, *bdaddr.bdaddr_t, *key, gto.i )
  hci_delete_stored_link_key.i( dd.i, *bdaddr.bdaddr_t, all.b, gto.i )
  hci_authenticate_link.i( dd.i, handle.w, gto.i )
  hci_encrypt_link.i( dd.i, handle.w, encrypt.b, gto.i )
  hci_change_link_key.i( dd.i, handle.w, gto.i )
  hci_switch_role.i( dd.i, *bdaddr.bdaddr_t, role.b, gto.i )
  hci_park_mode.i( dd.i, handle.w, max_interval.w, min_interval.w, gto.i )
  hci_exit_park_mode.i( dd.i, handle.w, gto.i )
  hci_read_inquiry_scan_type.i( dd.i, *type, gto.i )
  hci_write_inquiry_scan_type.i( dd.i, type,b, gto.i )
  hci_read_inquiry_mode.i( dd.i, *mode, gto.i )
  hci_write_inquiry_mode.i( dd.i, mode.b, gto.i )
  hci_read_afh_mode.i( dd.i, *mode, gto.i )
  hci_write_afh_mode.i( dd.i, mode.b, gto.i )
  hci_read_ext_inquiry_response.i( dd.i, *fec, *Datas, gto.i )
  hci_write_ext_inquiry_response.i( dd.i, fec.b, *Datas, gto.i )
  hci_read_simple_pairing_mode.i( dd.i, *mode, gto.i )
  hci_write_simple_pairing_mode.i( dd.i, mode.b, gto.i )
  hci_read_local_oob_data.i(  dd.i, *hash, *randomizer, gto.i )
  hci_read_inq_response_tx_power_level.i( dd.i, *level, gto.i )
  hci_read_inquiry_transmit_power_level.i( dd.i, *level, gto.i )
  hci_write_inquiry_transmit_power_level.i( dd.i, level.b, gto.i )
  hci_read_transmit_power_level.i( dd.i, handle.w, type.b, *level, gto.i )
  hci_read_link_policy.i( dd.i, handle.w, *policy, gto.i )
  hci_write_link_policy.i( dd.i, handle.w, policy.w, gto.i )
  hci_read_link_supervision_timeout.i( dd.i, handle.w, *timeout, gto.i )
  hci_write_link_supervision_timeout.i( dd.i, handle.w, timeout.w, gto.i )
  hci_set_afh_classification.i( dd.i, *Mapi, gto.i )
  hci_read_link_quality.i( dd.i, handle.w, *link_quality, gto.i )
  hci_read_rssi.i( dd.i, handle.w, *rssi, gto.i )
  hci_read_afh_map.i( dd.i, handle.w, *mode, *Mapi, gto.i )
  hci_read_clock.i( dd.i, handle.w, which.b, *clock, *accuracy, gto.i )
  
  hci_le_set_scan_enable.i( dev_id.i, enable.b, filter_dup.b, gto.i )
  hci_le_set_scan_parameters.i( dev_id.i, type.b, interval.w, window.w, uown_type.b, filter.b, gto.i )
  hci_le_set_advertise_enable.i( dev_id.i, enable.b, gto.i)
  hci_le_create_conn.i( dd.i, interval.w, window.w, initiator_filter.b, *peer_bdaddr_type.bdaddr_t, own_bdaddr_type.b, min_interval.w, max_interval.w, latency.w, supervision_timeout.w, min_ce_length.w, max_ce_length.w, *handle, gto.i )
  hci_le_conn_update.i( dd.i, handle.w, min_interval.w, max_interval.w, latency.w, supervision_timeout.w, gto.i )
  hci_le_add_white_list.i( dd.i, *bdaddr.bdaddr_t, type.b, gto.i )
  hci_le_rm_white_list.i( dd.i, *bdaddr.bdaddr_t, type.b, gto.i )
  hci_le_read_white_list_size.i( dd.i, *size, gto.i )
  hci_le_clear_white_list.i( dd.i, gto.i )
  hci_le_add_resolving_list.i( dd.i, *bdaddr.bdaddr_t, type.b, *peer_irk, *local_irk, gto.i )
  hci_le_rm_resolving_list.i( dd.i, *bdaddr.bdaddr_t, type.b, gto.i )
  hci_le_clear_resolving_list.i( dd.i, gto.i )
  hci_le_read_resolving_list_size.i( dd.i, *size, gto.i )
  hci_le_set_address_resolution_enable.i( dev_id.i, enable.b, gto.i )
  hci_le_read_remote_features.i( dd.i, handle.w, *features, gto.i )
  
  ;hci_for_each_dev( flag.i, Int(*func)(int dd, int dev_id, long arg), long arg);
  hci_get_route.u( *bdaddr.bdaddr_t )
  
  hci_bustostr.i( bus.i )
  hci_typetostr.i( type.i )
  hci_dtypetostr.i( type.i )
  hci_dflagstostr.i( flags.l )
  hci_ptypetostr.i( ptype.i )
  hci_strtoptype.i( *str, *val)
  hci_scoptypetostr.i( ptype.i )
  hci_strtoscoptype.i( *str, *val)
  hci_lptostr.i( ptype.i )
  hci_strtolp.i( *str, *val )
  hci_lmtostr.i( ptype.i )
  hci_strtolm.i( *str, *val )
  
  hci_cmdtostr.i( cmd.i )
  hci_commandstostr.i( *commands, *pref, width.i )
  
  hci_vertostr.i( ver.i )
  hci_strtover.i( *str, *ver )
  lmp_vertostr.i( ver.i )
  lmp_strtover.i( *str, *ver )
  pal_vertostr.i( ver.i )
  pal_strtover.i( *str, *ver )
  
  lmp_featurestostr.i( *features, *pref, width.i )
  
  baswap.i( *dst.bdaddr_t, *src.bdaddr_t )
  strtoba.i( *str )
  ba2str.i( *ba.bdaddr_t, *str )
  str2ba.i( *str, *ba.bdaddr_t )
  ba2oui.i( *ba.bdaddr_t, *oui)
  bachk.i( *str )
  bt_free( *ptr )
  bt_error.i( code.w )
EndImport

;-Bluetooth Start
Define ii.inquiry_info
Define max_rsp.i, num_rsp.i
Define dev_id.i, sock.i, len.i, flags.i
Define i.i
Define addr.s{19}
Define name.s{248}
Define dr.hci_dev_req

OpenConsole("Bluetooth-Test!")

dev_id = hci_get_route(0)
sock = hci_open_dev(dev_id)

dr\dev_id  = dev_id
;dr\dev_opt = #SCAN_DISABLED
dr\dev_opt = #SCAN_PAGE|#SCAN_INQUIRY

;*dr2 = @dr

If ioctl_(sock, #HCISETSCAN, @dr) < 0
  Print(~"Der Bluetooth-Adapter konnte nicht auf Sichtbar geschaltet werden.\nBeachte:\nDieses Programm muss mit Root-Rechten ausgeführt werden.\n\n")
  End
Else
  Print(~"Alles Supi!\nDer Bluetooth-Adapter wurde auf Sichtbar geschaltet. (Vielleicht!) \nBitte überprüfen sie in ihren Bluetooth-Einstellung ob es geklappt hat.\n\n")
EndIf

CloseConsole()
Zum freien Probieren und Basteln. (Müsste jetzt funktionieren, aber einige Definitionen sind garantiert noch überarbeitbar.)