;Bluetooth driver routines include "settings.inc" include "ti83plus.inc" include "equates.inc" include "usb8x.inc" include "bluetooth.inc" SEGMENT Main GLOBALS ON EXTERN BluetoothCallbackRunner,BluetoothCallbackRunnerEnd EXTERN SendHCICommand,HCI_SetLocalDeviceName,HCI_SetDeviceClass,RequestHCIData EXTERN IPutC,DispHexA,IGetKey,PutHexA,HCI_SetScanMode,RequestHCIData_NoWait InitializeBluetooth: ;Initializes the USB Bluetooth adapter. ;Set up a small RAM loader for the callback routine to get back to this page in a,(6) ld (basePage),a ld hl,BluetoothCallbackRunner ld de,BluetoothCallbackLoc ld bc,BluetoothCallbackRunnerEnd-BluetoothCallbackRunner ldir ld de,BluetoothCallbackLoc U_CALL SetCallBack ;Initialize the USB device U_CALL HostInit ret c ld hl,eventDataBuffer ;Make sure this is really a Bluetooth USB adapter ;If this has to read from the config descriptor, there's a chance it will fail, but if it has to ; resort to the config descriptor, there's also more of a chance it will work, so oh well U_CALL GetClass ret c cp 0E0h ;bDeviceClass scf ld a,errInvalidDeviceClass ret nz dec b ;bSubClass scf ld a,errInvalidDeviceClass ret nz dec c ;bProtocol scf ld a,errInvalidDeviceClass ret nz ;Read the device descriptor, because I was doing that early in testing and things work that way ld hl,eventDataBuffer ld b,descDevice U_CALL ReadDescriptor ;Read the start of the config descriptor to determine the size ld hl,sGetConfigDescriptor ld de,eventDataBuffer ld bc,8 push de ldir pop hl ld b,9 ld de,eventDataBuffer U_CALL SendControlData ret c ;Read the majority of the config descriptor ourselves since usb8x can't do it because it's so long ld bc,(eventDataBuffer+2) ld hl,128 or a sbc hl,bc jr nc,$F ld bc,128 $$: push bc ld hl,sGetConfigDescriptor ld de,eventDataBuffer ld bc,8 push de ldir pop hl pop bc ld a,c ld (eventDataBuffer+6),a ld b,a ld de,eventDataBuffer U_CALL SendControlData ret c ;Configure it ld b,1 U_CALL ConfigureDevice ret c ;Parse eventDataBuffer for the endpoint descriptors ld ix,eventDataBuffer call FindEndpointDescriptor ld b,3 ;set up the first three descriptors (hopefully that'll always be an interrupt and two bulk pipes) push bc jr $F pipeSetupLoop: push bc call FindEndpointDescriptorAgain $$: ld a,(ix+4) ;max packet size / 8 srl a srl a srl a ld d,a ld e,(ix+6) ;polling interval ld a,e ld a,(ix+3) ;endpoint type cp 03h ;interrupt jr nz,$F ;Set up the interrupt pipe ld a,(ix+2) and 7Fh ld (interruptPipe),a ld b,a ld c,pipeInt U_CALL SetupInPipe jr pipeSetupContinue $$: cp 02h ;bulk jr nz,pipeSetupContinue ;ignore other endpoints ld a,(ix+2) bit 7,a jr z,$F ;This is an input bulk pipe and 7Fh ld (dataInPipe),a ld b,a ld c,pipeBulk U_CALL SetupInPipe jr pipeSetupContinue $$: ;This is an output bulk pipe and 7Fh ld (dataOutPipe),a ld b,a ld c,pipeBulk U_CALL SetupOutPipe pipeSetupContinue: pop bc djnz pipeSetupLoop ld hl,responseFlag ld (hl),0 call ResetBluetoothDevice ret c ;Set local name to TI84P/TI84PSE plus the first 5 digits of the calc ID B_CALL ZeroOP1 B_CALL OP1ToOP4 B_CALL GetCalcSerial ld de,OP1 ld hl,sCalcName ld bc,sCalcNameEnd-sCalcName in a,(21h) and 3 jr z,$F ld hl,sCalcNameSE ld bc,sCalcNameSEEnd-sCalcNameSE $$: ldir ex de,hl ld de,OP4 ld b,5 ld (hl),'_' inc hl $$: ld a,(de) call PutHexA inc de djnz $B ld (hl),0 ld hl,OP1 call HCI_SetLocalDeviceName ret c ;Set class of device (currently hard-coded to "palm-sized PDA/computer") ld hl,OP1 ld (hl),14h inc hl ld (hl),21h inc hl ld (hl),0 dec hl dec hl call HCI_SetDeviceClass ret c xor a ret sCalcName: DB "TI84P" sCalcNameEnd: sCalcNameSE: DB "TI84PSE" sCalcNameSEEnd: FindEndpointDescriptor: ld a,(ix+1) cp descEndpoint ret z FindEndpointDescriptorAgain: ld c,(ix+0) ld b,0 add ix,bc jr FindEndpointDescriptor sGetConfigDescriptor: DB 80h,06h,00h,02h,00h,00h,09h,00h KillBluetooth: ;Kills power to the USB Bluetooth adapter. U_CALL HostKill ret ResetBluetoothDevice: ;Resets the Bluetooth device. This is automatically done on initialization. ;Returns carry flag set if problems ld de,ogfHCBaseband*256+hciReset ld bc,0 jr SendHCICommand SetDiscoverableMode: ;Sets the Bluetooth device in "discoverable" mode, enabling it to respond to connection requests from remote devices. ;Outputs: ; Returns carry flag set if problems ;Become discoverable ld a,03h call HCI_SetScanMode ;Set up flags ld ix,responseFlag res receivedConnRequest,(ix+0) set inDiscoverableMode,(ix+0) ;Request more HCI events until we get to the "Connection Request" one we want ld hl,eventDataBuffer jr RequestHCIData_NoWait LeaveDiscoverableMode: ;Exits "discoverable" mode for the Bluetooth device, hiding it from inquiry scans from remote devices. ;Outputs: ; Returns carry flag set if problems ;Become non-discoverable res receivedConnRequest,(ix+0) res inDiscoverableMode,(ix+0) ld a,01h jr HCI_SetScanMode IsConnectionRequestPending: ;Returns whether a connection request from a remote device has been received and is pending response. ;Outputs: ; Returns NZ if request is pending ; If request is pending, HL points to BD_ADDR, Class_of_Device, and Link_Type ld ix,responseFlag bit receivedConnRequest,(ix+0) ld hl,deviceRequestInfo ret AcceptConnectionRequest: ;Accepts a pending connection request. ;Inputs: ; HL points to data block for device that requested connection: ; ;6; BD_ADDR ; ;3; Class_of_Device ; ;1; Link_Type ;Outputs: ; Returns carry flag set if problems ; HL contains pointer to connection handle: ; ;2; Connection_Handle ; ;6; BD_ADDR ; ;1; Link_Type ; ;1; Encryption_Enabled ld de,OP1 ld bc,6 ldir ld a,1 ;ACL link type ld (de),a ld hl,OP1 ld de,ogfLinkControl*256+hciAcceptConnectionRequest ld bc,7 ld ix,eventDataBuffer call SendHCICommand ret c ld hl,eventDataBuffer call RequestHCIData ret c ld a,(eventDataBuffer) cp Event_ConnectionComplete scf ret nz ld ix,responseFlag set deviceConnected,(ix+0) ld hl,eventDataBuffer+3 xor a ret RejectConnectionRequest: ;Rejects a pending connection request. ;Inputs: ; HL points to data block for device that requested connection: ; ;6; BD_ADDR ; ;3; Class_of_Device ; ;1; Link_Type ; A is the reason for the rejection (or 0 for default (Unacceptable BD_ADDR)) ;Outputs: ; Returns carry flag set if problems ld de,OP1 ld bc,6 ldir or a jr nz,$F ld a,0Fh ;Connection Rejected due to Unacceptable BD_ADDR $$: ld (de),a ld hl,OP1 ld de,ogfLinkControl*256+hciRejectConnectionRequest ld bc,7 ld ix,eventDataBuffer call SendHCICommand ret c ld hl,eventDataBuffer call RequestHCIData ret c ld a,(eventDataBuffer) cp Event_ConnectionComplete scf ret nz ld ix,responseFlag res deviceConnected,(ix+0) xor a ret