WinCE: Failed to open the created bluetooth virtual com port

0

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)
bluetooth
windows-ce
ctypes
python-2.5
pythonce
asked on Stack Overflow Apr 15, 2018 by Ben • edited Apr 15, 2018 by Ben

1 Answer

0

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.

answered on Stack Overflow Apr 19, 2018 by Ben • edited Apr 23, 2018 by Ben

User contributions licensed under CC BY-SA 3.0