I am trying to get Bluetooth printer to work on a WinCE handheld. The device is already set as trusted in Control Panel\Bluetooth Device Property
, PIN authenticated.
The RegisterDevice
call returns a device handle, without error, but when I try to open the port via CreateFileW
with OPEN_EXISTING, I got INVALID_HANDLE_VALUE
, with system error code 55 ERROR_DEV_NOT_EXIST
.
I am very new to WinCE API, new to C++ also. I can't see where the problem is.
What's wrong with my settings? Is there any extra steps to take before I can talk to the printer over this bt-vcom ?
My device is a WM5 HTC Diamond Phone. in its Communication Manager
>Bluetooth
>COM Port
section, I can't see any of the port I created (but they seems indeed created: listed in 3rd party app e.g. TerminalCE
, and reported as occupied when trying to create virtual com port in system GUI with these port.). If I create a different Outgoing Port
in the system GUI here, Python can talk to the printer progrogramatically via the new port.
Am not I using the same API after all... why mine not working ?
My code is adapted from https://msdn.microsoft.com/en-us/library/ms881004.aspx as follows:
# -*- coding: utf-8 -*-
from time import sleep
import ctypes
from ctypes import POINTER, Structure
from ctypes import c_ulonglong, c_int, pointer, c_ulong, c_wchar, c_char, c_ushort
from ctypes import windll, cdll
from ctypes import memset, addressof, sizeof, byref
from comtypes import GUID
from ceserial import Serial
import wintypex as w
# in wintypex
# ULONGLONG = c_ulonglong
# bt_addr = ULONGLONG
# BT_ADDR = POINTER(bt_addr)
# BT_ADDR_PTR = POINTER(BT_ADDR)
# uiportflags
RFCOMM_PORT_FLAGS_REMOTE_DCB = 0x00000001
RFCOMM_PORT_FLAGS_KEEP_DCD = 0x00000002
RFCOMM_PORT_FLAGS_AUTHENTICATE = 0x00000004
RFCOMM_PORT_FLAGS_ENCRYPT = 0x00000008
core = windll.coredll # windll.kernel32
RegisterDevice = core.RegisterDevice # HANDLE RegisterDevice( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib, DWORD dwInfo );
RegisterDevice.restype = w.HANDLE
RegisterDevice.argtypes = [ w.LPCWSTR, w.DWORD, w.LPCWSTR, w.DWORD ]
DeregisterDevice = core.DeregisterDevice
GetLastError = core.GetLastError
SetLastError = core.SetLastError
# For BT_COM support.
class PORTEMUPortParams(Structure):
_fields_=[
( 'channel', w.INT),
( 'flocal', w.INT ),
( 'device', w.BT_ADDR),
( 'imtu', w.INT ),
( 'iminmtu', w.INT ),
( 'imaxmtu', w.INT ),
( 'isendquota', w.INT ),
( 'irecvquota', w.INT ),
( 'uuidService', GUID ),
( 'uiportflags', w.UINT)
]
def __init__( self, device_str=None,
flocal=False,
channel = None,
uuidService=None,
uiportflags=None ):
if device_str is None and not flocal:
raise Exception( 'device address missing in client mode.' )
memset( addressof(self), 0, sizeof(self) ) # memset (&pp, 0, sizeof(pp));
if not flocal:
bta = c_ulonglong( int(device_str, 16) )
print(bta)
bta_p = w.BT_ADDR( bta )
self.deivce = bta_p
self.flocal = w.INT( flocal )
# https://stackoverflow.com/questions/27302060/how-to-check-if-an-paired-bluetooth-device-is-a-printer-or-a-scanner-android
# " Note: most common UUID (scanners, printers, Mice)
# have the generic UUID 0001101-0000-1000-8000-00805F9B34FB "
if uuidService:
self.uuidService = uuidService
else:
self.uuidService = GUID("{00001101-0000-1000-8000-00805F9B34FB}")
if uiportflags:
self.uiportflags = uiportflags
if channel:
self.channel = channel & 0xff # pp.channel = channel & 0xff;
print('class defined.')
print( "try uuidService" )
pp = PORTEMUPortParams('dc1d30428b19') # PORTEMUPortParams pp;
# pp.uiportflags = RFCOMM_PORT_FLAGS_AUTHENTICATE
# pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB
pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB | RFCOMM_PORT_FLAGS_AUTHENTICATE
#HANDLE h = RegisterDevice ("COM", index, "btd.dll", (DWORD)&pp );
for i in range (1,10):
index = i
SetLastError( w.DWORD(0) )
h = RegisterDevice(u"COM", index, u"btd.dll", w.DWORD( addressof(pp) ) )
if h :
try:
print( 'handle=', h )
print( "COM%s" % index )
s = Serial( port="COM%s:" % index, open_existing=True )
s.open()
s.write(u'HELLO\r\n')
s.flushOutput()
# s.write(u'HI\r\n')
# s.flushOutput()
s.close()
except:
pass
# sleep(2)
DeregisterDevice( h )
break
else:
print('failed', GetLastError())
sleep(1)
On Windows Mobile, two methods to create a port exist in the library, the first is class BluetoothSerialPort, this creates a connection immediately _but the underlying API it uses is rather unreliable, and it seems not to work at all on various device types._ The second is BluetoothDeviceInfo.SetServiceState as for Win32, this manually configures the necessary Registry settings and is reliable but might require a reboot before the port becomes available, and again the name of the new port is not returned.
https://github.com/inthehand/32feet/wiki/Bluetooth-Serial-Ports
a total waste of time...
PS: To control the bluetooth printer, wrapping the winsock functions in ctypes and communicating with the printer via bluetooth socket works flawlessly after some trial and error.
User contributions licensed under CC BY-SA 3.0