Skip to content

WIP: BLE HID #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
194 changes: 194 additions & 0 deletions ble/ble.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
//go:build tinygo && nrf52840

package ble

import (
"machine/usb/descriptor"
k "machine/usb/hid/keyboard"

"tinygo.org/x/bluetooth"
)

var adapter = bluetooth.DefaultAdapter
var reportIn bluetooth.Characteristic
var rx bluetooth.DeviceCharacteristic

var reportMap = descriptor.CDCHID.HID[2]

func init() {
adapter.Enable()
}

type bleKeyboard struct {
keyboard
Name string
report [9]byte
connected bool
}

func NewKeyboard(name string) *bleKeyboard {
return &bleKeyboard{
Name: name,
}
}

func (k *bleKeyboard) Connect() error {
var err error

bluetooth.SetSecParamsBonding()
bluetooth.SetSecCapabilities(bluetooth.NoneGapIOCapability)

name := k.Name
if len(name) > 14 {
name = name[:14]
}

adv := adapter.DefaultAdvertisement()
adv.Configure(bluetooth.AdvertisementOptions{
LocalName: name,
ServiceUUIDs: []bluetooth.UUID{
bluetooth.ServiceUUIDDeviceInformation,
bluetooth.ServiceUUIDBattery,
bluetooth.ServiceUUIDHumanInterfaceDevice,
},
})

err = adv.Start()
if err != nil {
return err
}

k.registerHID()

return nil
}

func (k *bleKeyboard) registerHID() error {
adapter.AddService(&bluetooth.Service{
UUID: bluetooth.ServiceUUIDDeviceInformation,
Characteristics: []bluetooth.CharacteristicConfig{
{
UUID: bluetooth.CharacteristicUUIDManufacturerNameString,
Flags: bluetooth.CharacteristicReadPermission,
Value: []byte("Nice Keyboards"),
},
{
UUID: bluetooth.CharacteristicUUIDModelNumberString,
Flags: bluetooth.CharacteristicReadPermission,
Value: []byte("nice!nano"),
},
{
UUID: bluetooth.CharacteristicUUIDPnPID,
Flags: bluetooth.CharacteristicReadPermission,
Value: []byte{0x02, 0x8a, 0x24, 0x66, 0x82, 0x34, 0x36},
//Value: []byte{0x02, uint8(0x10C4 >> 8), uint8(0x10C4 & 0xff), uint8(0x0001 >> 8), uint8(0x0001 & 0xff)},
},
},
})
adapter.AddService(&bluetooth.Service{
UUID: bluetooth.ServiceUUIDBattery,
Characteristics: []bluetooth.CharacteristicConfig{
{
UUID: bluetooth.CharacteristicUUIDBatteryLevel,
Value: []byte{80},
Flags: bluetooth.CharacteristicReadPermission | bluetooth.CharacteristicNotifyPermission,
},
},
})
// gacc
/*
device name r
apperance r
peripheral prefreed connection

*/

adapter.AddService(&bluetooth.Service{
UUID: bluetooth.ServiceUUIDGenericAccess,
Characteristics: []bluetooth.CharacteristicConfig{
{
UUID: bluetooth.CharacteristicUUIDDeviceName,
Flags: bluetooth.CharacteristicReadPermission,
Value: []byte("tinygo-corne"),
},
{

UUID: bluetooth.New16BitUUID(0x2A01),
Flags: bluetooth.CharacteristicReadPermission,
Value: []byte{uint8(0x03c4 >> 8), uint8(0x03c4 & 0xff)}, /// []byte(strconv.Itoa(961)),
},
// {
// UUID: bluetooth.CharacteristicUUIDPeripheralPreferredConnectionParameters,
// Flags: bluetooth.CharacteristicReadPermission,
// Value: []byte{0x02},
// },

// // //
},
})

// hid
adapter.AddService(&bluetooth.Service{
UUID: bluetooth.ServiceUUIDHumanInterfaceDevice,
/*
- hid information r
- report map r
- report nr
- client charecteristic configuration
- report reference
- report nr
- client charecteristic configuration
- report reference
- hid control point wnr
*/
Characteristics: []bluetooth.CharacteristicConfig{
// {
// UUID: bluetooth.CharacteristicUUIDHIDInformation,
// Flags: bluetooth.CharacteristicReadPermission,
// Value: []byte{uint8(0x0111 >> 8), uint8(0x0111 & 0xff), uint8(0x0002 >> 8), uint8(0x0002 & 0xff)},
// },
{
//Handle: &reportmap,
UUID: bluetooth.CharacteristicUUIDReportMap,
Flags: bluetooth.CharacteristicReadPermission,
Value: reportMap,
},
{

Handle: &reportIn,
UUID: bluetooth.CharacteristicUUIDReport,
Value: k.report[:],
Flags: bluetooth.CharacteristicReadPermission | bluetooth.CharacteristicNotifyPermission,
},
{
// protocl mode
UUID: bluetooth.New16BitUUID(0x2A4E),
Flags: bluetooth.CharacteristicWriteWithoutResponsePermission | bluetooth.CharacteristicReadPermission,
// Value: []byte{uint8(1)},
// WriteEvent: func(client bluetooth.Connection, offset int, value []byte) {
// print("protocol mode")
// },
},
{
UUID: bluetooth.CharacteristicUUIDHIDControlPoint,
Flags: bluetooth.CharacteristicWriteWithoutResponsePermission,
// Value: []byte{0x02},
},
},
})

return nil
}

func (k *bleKeyboard) Up(c k.Keycode) error {
return k.keyboard.Up(Keycode(c))
}

func (k *bleKeyboard) Down(c k.Keycode) error {
return k.keyboard.Down(Keycode(c))
}

func sendBLEPacket(b []byte) error {
_, err := reportIn.Write(b)
return err
}
89 changes: 89 additions & 0 deletions ble/blesplit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//go:build tinygo && nrf52840

package ble

import (
k "machine/usb/hid/keyboard"

"tinygo.org/x/bluetooth"
)

var tx = &bluetooth.Characteristic{}

type bleSplitKeyboard struct {
keyboard
Name string
report [9]byte
pressed []k.Keycode
connected bool
}

func NewSplitKeyboard(name string) *bleSplitKeyboard {
return &bleSplitKeyboard{
Name: name,
}
}

func (k *bleSplitKeyboard) Connect() error {
var err error

name := k.Name
if len(name) > 14 {
name = name[:14]
}
adapter.SetConnectHandler(func(device bluetooth.Address, connected bool) {
println("connected:", connected)
})

adv := adapter.DefaultAdvertisement()
err = adv.Configure(bluetooth.AdvertisementOptions{
LocalName: name,
})
err = adv.Start()
if err != nil {
return err
}

adapter.AddService(&bluetooth.Service{
UUID: bluetooth.ServiceUUIDNordicUART,
Characteristics: []bluetooth.CharacteristicConfig{
{
Handle: tx,
UUID: bluetooth.CharacteristicUUIDUARTTX,
Value: k.report[:3],
Flags: bluetooth.CharacteristicReadPermission | bluetooth.CharacteristicNotifyPermission,
},
},
})
return nil
}

func (k *bleSplitKeyboard) Up(c k.Keycode) error {
for i, p := range k.pressed {
if c == p {
k.pressed = append(k.pressed[:i], k.pressed[i+1:]...)
row := byte(c >> 8)
col := byte(c)
_, err := tx.Write([]byte{0x55, byte(row), byte(col)})
return err
}
}
return nil
}

func (k *bleSplitKeyboard) Down(c k.Keycode) error {
found := false
for _, p := range k.pressed {
if c == p {
found = true
}
}
if !found {
k.pressed = append(k.pressed, c)
row := byte(c >> 8)
col := byte(c)
_, err := tx.Write([]byte{0xAA, byte(row), byte(col)})
return err
}
return nil
}
Loading