namespace pxt . packetio { export interface TalkArgs { cmd : number ; data ? : Uint8Array ; } export interface PacketIOWrapper { readonly io : PacketIO ; icon : string ; familyID : number ; onSerial : ( buf : Uint8Array , isStderr : boolean ) => void ; reconnectAsync ( ) : Promise < void > ; disconnectAsync ( ) : Promise < void > ; reflashAsync ( resp ) : Promise < void > ; onCustomEvent : ( type : string , payload : Uint8Array ) => void ; sendCustomEventAsync ( type , payload ) : Promise < void > ; unsupportedParts ? ( ) : string [ ] ; } export interface PacketIO { sendPacketAsync ( pkt ) : Promise < void > ; recvPacketAsync ? : ( ) => Promise < Uint8Array > ; onDeviceConnectionChanged : ( connect : boolean ) => void ; onConnectionChanged : ( ) => void ; onData : ( v : Uint8Array ) => void ; onError : ( e : Error ) => void ; onEvent : ( v : Uint8Array ) => void ; error ( msg ) : any ; reconnectAsync ( ) : Promise < void > ; disconnectAsync ( ) : Promise < void > ; isConnecting ( ) : boolean ; isConnected ( ) : boolean ; isSwitchingToBootloader ? : ( ) => void ; disposeAsync ( ) : Promise < void > ; talksAsync ? ( cmds ) : Promise < Uint8Array [ ] > ; sendSerialAsync ? ( buf , useStdErr ) : Promise < void > ; onSerial ? : ( v : Uint8Array , isErr : boolean ) => void ; } export let mkPacketIOAsync ; export let mkPacketIOWrapper ; let wrapper ; let initPromise ; let onConnectionChangedHandler = ( ) => { } ; let onSerialHandler ; let onCustomEventHandler ; /**
     * A DAP wrapper is active
     */ export function isActive ( ) { return ! ! wrapper ; } /**
     * The DAP wrapper is active and the device is connected
     */ export function isConnected ( ) { return ! ! wrapper && wrapper . io . isConnected ( ) ; } export function isConnecting ( ) { return ! ! wrapper && wrapper . io . isConnecting ( ) ; } export function icon ( ) { return ! ! wrapper && ( wrapper . icon || pxt . appTarget . appTheme . downloadDialogTheme ?. deviceIcon || "usb" ) ; } export function unsupportedParts ( ) { return wrapper ?. unsupportedParts ? wrapper . unsupportedParts ( ) : [ ] ; } let disconnectPromise ; export function disconnectAsync ( ) { if ( disconnectPromise ) return disconnectPromise ; let p = Promise . resolve ( ) ; if ( wrapper ) { debug ( 'packetio: disconnect' ) ; const w = wrapper ; p = p . then ( ( ) => w . disconnectAsync ( ) ) . then ( ( ) => w . io . disposeAsync ( ) ) . catch ( e => { pxt . reportException ( e ) ; } ) . finally ( ( ) => { initPromise = undefined ; wrapper = undefined ; disconnectPromise = undefined ; } ) ; if ( onConnectionChangedHandler ) p = p . then ( ( ) => onConnectionChangedHandler ( ) ) ; disconnectPromise = p ; } return p ; } export function configureEvents ( onConnectionChanged , onSerial , onCustomEvent ) { onConnectionChangedHandler = onConnectionChanged ; onSerialHandler = onSerial ; onCustomEventHandler = onCustomEvent ; if ( wrapper ) { wrapper . io . onConnectionChanged = onConnectionChangedHandler ; wrapper . onSerial = onSerialHandler ; wrapper . onCustomEvent = onCustomEvent ; } } export function sendCustomEventAsync ( type , payload ) { if ( wrapper ) return wrapper . sendCustomEventAsync ( type , payload ) ; else return Promise . resolve ( ) ; } function wrapperAsync ( ) { if ( wrapper ) return Promise . resolve ( wrapper ) ; if ( ! mkPacketIOAsync ) { pxt . debug ( `packetio: not defined, skipping` ) ; return Promise . resolve ( undefined ) ; } pxt . debug ( `packetio: new wrapper` ) ; return mkPacketIOAsync ( ) . then ( io => { io . onConnectionChanged = onConnectionChangedHandler ; wrapper = mkPacketIOWrapper ( io ) ; if ( onSerialHandler ) wrapper . onSerial = onSerialHandler ; if ( onCustomEventHandler ) wrapper . onCustomEvent = onCustomEventHandler ; if ( onConnectionChangedHandler ) onConnectionChangedHandler ( ) ; return wrapper ; } ) ; } export function initAsync ( force = false ) { pxt . debug ( `packetio: init ${ force ? "(force)" : "" }` ) ; if ( ! initPromise ) { let p = Promise . resolve ( ) ; if ( force ) p = p . then ( ( ) => disconnectAsync ( ) ) ; initPromise = p . then ( ( ) => wrapperAsync ( ) ) . finally ( ( ) => { initPromise = undefined ; } ) ; } return initPromise ; } }