AppleUSBCDCDriver.h [plain text]
#define LDEBUG 0 // for debugging
#define USE_ELG 0 // to Event LoG (via XTrace) - LDEBUG must also be set
#define USE_IOL 0 // to IOLog - LDEBUG must also be set
#define LOG_DATA 0 // logs data to the appropriate log - LDEBUG must also be set
#define DUMPALL 0 // Dumps all the data to the log - LOG_DATA must also be set
#define Sleep_Time 20
#if LDEBUG
#if USE_ELG
#include "XTrace.h"
#define XTRACE(id, x, y, msg) \
do \
{ \
if (gXTrace) \
{ \
static char *__xtrace = 0; \
if (__xtrace) \
gXTrace->LogAdd((UInt32)id, (UInt32)(x), (UInt32)(y), __xtrace); \
else \
__xtrace = gXTrace->LogAdd((UInt32)id, (UInt32)(x), (UInt32)(y), "AppleUSBCDCDriver: " msg, false); \
} \
} while(0)
#define XTRACE2(id, x, y, msg) XTRACE_HELPER(gXTrace, (UInt32)id, x, y, "AppleUSBCDCDriver: " msg)
#else
#if USE_IOL
#define XTRACE(ID,A,B,STRING) {IOLog("%8x %8x %8x %8x AppleUSBCDCDriver: " STRING "\n",(unsigned int)(ID),(unsigned int)(A),(unsigned int)(B), (unsigned int)IOThreadSelf()); IOSleep(Sleep_Time);}
#else
#define XTRACE(id, x, y, msg)
#endif
#endif
#if LOG_DATA
#define LogData(D, C, b, ID) USBLogData((UInt8)D, (UInt32)C, (char *)b, ID)
#else
#define LogData(D, C, b, ID)
#endif
#else
#define XTRACE(id, x, y, msg)
#define LogData(D, C, b, ID)
#undef USE_ELG
#undef USE_IOL
#undef LOG_DATA
#endif
#define ALERT(A,B,STRING) IOLog("%8x %8x AppleUSBCDCDriver: " STRING "\n", (unsigned int)(A), (unsigned int)(B))
#define baseName "usbmodem"
#define defaultName "USB Modem"
#define numberofPorts 4 // Number of ports we'll support
#define productNameLength 32 // Arbitrary length
#define propertyTag "Product Name"
#define kDefaultBaudRate 9600
#define kMaxBaudRate 230400
#define kMaxCirBufferSize 4096
#define kPipeStalled 1
#define kDeviceSelfPowered 1
enum
{
kDataIn = 0,
kDataOut,
kDataOther
};
#define kUSBAbstractControlModel 2
#define kUSBv25 1
#define kUSBbRxCarrier 0x01 // Carrier Detect
#define kUSBDCD kUSBbRxCarrier
#define kUSBbTxCarrier 0x02 // Data Set Ready
#define kUSBDSR kUSBbTxCarrier
#define kUSBbBreak 0x04
#define kUSBbRingSignal 0x08
#define kUSBbFraming 0x10
#define kUSBbParity 0x20
#define kUSBbOverRun 0x40
#define kDTROff 0
#define kRTSOff 0
#define kDTROn 1
#define kRTSOn 2
enum
{
kUSBSEND_ENCAPSULATED_COMMAND = 0, kUSBGET_ENCAPSULATED_RESPONSE = 1,
kUSBSET_COMM_FEATURE = 2,
kUSBGET_COMM_FEATURE = 3,
kUSBCLEAR_COMM_FEATURE = 4,
kUSBSET_LINE_CODING = 0x20,
kUSBGET_LINE_CODING = 0x21,
kUSBSET_CONTROL_LINE_STATE = 0x22,
kUSBSEND_BREAK = 0x23
};
enum
{
kUSBNETWORK_CONNECTION = 0, kUSBRESPONSE_AVAILABLE = 1,
kUSBSERIAL_STATE = 0x20
};
typedef struct
{
UInt32 dwDTERate;
UInt8 bCharFormat;
UInt8 bParityType;
UInt8 bDataBits;
} LineCoding;
#define dwDTERateOffset 0
#define wValueOffset 2
#define wIndexOffset 4
#define wLengthOffset 6
enum
{
CS_INTERFACE = 0x24,
Header_FunctionalDescriptor = 0x00,
CM_FunctionalDescriptor = 0x01,
ACM_FunctionalDescriptor = 0x02,
Union_FunctionalDescriptor = 0x06,
CS_FunctionalDescriptor = 0x07,
CM_ManagementData = 0x01,
CM_ManagementOnData = 0x02,
ACM_DeviceSuppCommFeature = 0x01,
ACM_DeviceSuppControl = 0x02,
ACM_DeviceSuppBreak = 0x04,
ACM_DeviceSuppNetConnect = 0x08
};
typedef struct
{
UInt8 bFunctionLength;
UInt8 bDescriptorType;
UInt8 bDescriptorSubtype;
} FunctionalDescriptorHeader;
typedef struct
{
UInt8 bFunctionLength;
UInt8 bDescriptorType;
UInt8 bDescriptorSubtype;
UInt8 bmCapabilities;
UInt8 bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
UInt8 bFunctionLength;
UInt8 bDescriptorType;
UInt8 bDescriptorSubtype;
UInt8 bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
UInt8 bFunctionLength;
UInt8 bDescriptorType;
UInt8 bDescriptorSubtype;
UInt8 bMasterInterface;
UInt8 bSlaveInterface[];
} UnionFunctionalDescriptor;
enum ParityType
{
NoParity = 0,
OddParity,
EvenParity
};
typedef struct CirQueue
{
UInt8 *Start;
UInt8 *End;
UInt8 *NextChar;
UInt8 *LastChar;
size_t Size;
size_t InQueue;
} CirQueue;
typedef enum QueueStatus
{
queueNoError = 0,
queueFull,
queueEmpty,
queueMaxStatus
} QueueStatus;
enum
{
kCDCPowerOffState = 0,
kCDCPowerOnState = 1,
kNumCDCStates = 2
};
#define BIGGEST_EVENT 3
#define SPECIAL_SHIFT (5)
#define SPECIAL_MASK ((1<<SPECIAL_SHIFT) - 1)
#define STATE_ALL (PD_RS232_S_MASK | PD_S_MASK)
#define FLOW_RX_AUTO (PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO)
#define FLOW_TX_AUTO (PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD)
#define CAN_BE_AUTO (FLOW_RX_AUTO | FLOW_TX_AUTO)
#define CAN_NOTIFY (PD_RS232_N_MASK)
#define EXTERNAL_MASK (PD_S_MASK | (PD_RS232_S_MASK & ~PD_RS232_S_LOOP))
#define INTERNAL_DELAY (PD_RS232_S_LOOP)
#define DEFAULT_AUTO (PD_RS232_A_RFR | PD_RS232_A_CTS | PD_RS232_A_DSR)
#define DEFAULT_NOTIFY 0x00
#define DEFAULT_STATE (PD_S_TX_ENABLE | PD_S_RX_ENABLE | PD_RS232_A_TXO | PD_RS232_A_RXO)
#define IDLE_XO 0
#define NEEDS_XOFF 1
#define SENT_XOFF -1
#define NEEDS_XON 2
#define SENT_XON -2
#define MAX_BLOCK_SIZE PAGE_SIZE
#define COMM_BUFF_SIZE 16
#define DATA_BUFF_SIZE 64
typedef struct
{
UInt32 ints;
UInt32 txInts;
UInt32 rxInts;
UInt32 mdmInts;
UInt32 txChars;
UInt32 rxChars;
} Stats_t;
typedef struct BufferMarks
{
unsigned long BufferSize;
unsigned long HighWater;
unsigned long LowWater;
bool OverRun;
} BufferMarks;
typedef struct
{
UInt32 State;
UInt32 WatchStateMask;
IOCommandGate *commandGate;
CirQueue RX;
CirQueue TX;
BufferMarks RXStats;
BufferMarks TXStats;
UInt32 CharLength;
UInt32 StopBits;
UInt32 TX_Parity;
UInt32 RX_Parity;
UInt32 BaudRate;
UInt8 FCRimage;
UInt8 IERmask;
bool MinLatency;
UInt8 XONchar;
UInt8 XOFFchar;
UInt32 SWspecial[ 0x100 >> SPECIAL_SHIFT ];
UInt32 FlowControl;
int RXOstate; int TXOstate;
IOThread FrameTOEntry;
mach_timespec DataLatInterval;
mach_timespec CharLatInterval;
bool AreTransmitting;
IOUSBInterface *CommInterface;
IOUSBInterface *DataInterface;
IOUSBPipe *InPipe;
IOUSBPipe *OutPipe;
IOUSBPipe *CommPipe;
IOBufferMemoryDescriptor *CommPipeMDP;
IOBufferMemoryDescriptor *PipeInMDP;
IOBufferMemoryDescriptor *PipeOutMDP;
UInt8 *CommPipeBuffer;
UInt8 *PipeInBuffer;
UInt8 *PipeOutBuffer;
IOUSBCompletion fCommCompletionInfo;
IOUSBCompletion fReadCompletionInfo;
IOUSBCompletion fWriteCompletionInfo;
IOUSBCompletion fMERCompletionInfo;
UInt8 CommInterfaceNumber;
UInt8 DataInterfaceNumber;
SInt32 Count;
UInt32 OutPacketSize;
UInt32 InPacketSize;
UInt8 CMCapabilities; UInt8 ACMCapabilities;
UInt32 LastCharLength;
UInt32 LastStopBits;
UInt32 LastTX_Parity;
UInt32 LastBaudRate;
} PortInfo_t;
typedef struct
{
void *arg1;
void *arg2;
void *arg3;
void *arg4;
PortInfo_t *port;
} parmList;
static inline unsigned long tval2long(mach_timespec val)
{
return (val.tv_sec * NSEC_PER_SEC) + val.tv_nsec;
}
static inline mach_timespec long2tval(unsigned long val)
{
mach_timespec tval;
tval.tv_sec = val / NSEC_PER_SEC;
tval.tv_nsec = val % NSEC_PER_SEC;
return tval;
}
class AppleUSBCDCDriver : public IOSerialDriverSync
{
OSDeclareDefaultStructors(AppleUSBCDCDriver);
private:
UInt8 fSessions; bool fTerminate; bool fStopping; bool fSuspendOK; UInt8 fPowerState; UInt8 fbmAttributes; UInt8 fProductName[productNameLength]; PortInfo_t *fPorts[numberofPorts];
static void commReadComplete( void *obj, void *param, IOReturn ior, UInt32 remaining);
static void dataReadComplete( void *obj, void *param, IOReturn ior, UInt32 remaining);
static void dataWriteComplete(void *obj, void *param, IOReturn ior, UInt32 remaining);
static void merWriteComplete(void *obj, void *param, IOReturn ior, UInt32 remaining);
public:
IOUSBDevice *fpDevice;
IOWorkLoop *fWorkLoop;
virtual bool start(IOService *provider);
virtual void stop(IOService *provider);
virtual IOReturn message(UInt32 type, IOService *provider, void *argument = 0);
virtual IOReturn acquirePort(bool sleep, void *refCon);
virtual IOReturn releasePort(void *refCon);
virtual UInt32 getState(void *refCon);
virtual IOReturn setState(UInt32 state, UInt32 mask, void *refCon);
virtual IOReturn watchState(UInt32 *state, UInt32 mask, void *refCon);
virtual UInt32 nextEvent(void *refCon);
virtual IOReturn executeEvent(UInt32 event, UInt32 data, void *refCon);
virtual IOReturn requestEvent(UInt32 event, UInt32 *data, void *refCon);
virtual IOReturn enqueueEvent(UInt32 event, UInt32 data, bool sleep, void *refCon);
virtual IOReturn dequeueEvent(UInt32 *event, UInt32 *data, bool sleep, void *refCon);
virtual IOReturn enqueueData(UInt8 *buffer, UInt32 size, UInt32 * count, bool sleep, void *refCon);
virtual IOReturn dequeueData(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon);
static IOReturn stopAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn acquirePortAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn releasePortAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn getStateAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn setStateAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn watchStateAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn executeEventAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn enqueueDataAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn dequeueDataAction(OSObject *owner, void *arg0, void *, void *, void *);
virtual void stopGated(PortInfo_t *port);
virtual IOReturn acquirePortGated(bool sleep, PortInfo_t *port);
virtual IOReturn releasePortGated(PortInfo_t *port);
virtual UInt32 getStateGated(PortInfo_t *port);
virtual IOReturn setStateGated(UInt32 state, UInt32 mask, PortInfo_t *port);
virtual IOReturn watchStateGated(UInt32 *state, UInt32 mask, PortInfo_t *port);
virtual IOReturn executeEventGated(UInt32 event, UInt32 data, PortInfo_t *port);
virtual IOReturn enqueueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, PortInfo_t *port);
virtual IOReturn dequeueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, PortInfo_t *port);
void cleanUp(void);
bool configureDevice(UInt8 numConfigs);
bool initDevice(UInt8 numConfigs);
bool getFunctionalDescriptors(PortInfo_t *port);
bool createSuffix(PortInfo_t *port, unsigned char *sufKey);
bool createSerialStream(PortInfo_t *port);
bool setUpTransmit(PortInfo_t *port);
void startTransmission(PortInfo_t *port);
void USBSetLineCoding(PortInfo_t *port);
void USBSetControlLineState(PortInfo_t *port, bool RTS, bool DTR);
void USBSendBreak(PortInfo_t *port, bool sBreak);
IOReturn clearPipeStall(PortInfo_t *port, IOUSBPipe *thePipe);
bool initPort(PortInfo_t *port);
void initStructure(PortInfo_t *port);
void setStructureDefaults(PortInfo_t *port);
bool allocateResources(PortInfo_t *port);
void releaseResources(PortInfo_t *port);
void freeRingBuffer(PortInfo_t *port, CirQueue *Queue);
bool allocateRingBuffer(PortInfo_t *port, CirQueue *Queue, size_t BufferSize);
bool WakeonRing(void);
private:
QueueStatus AddBytetoQueue(CirQueue *Queue, char Value);
QueueStatus GetBytetoQueue(CirQueue *Queue, UInt8 *Value);
QueueStatus InitQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size);
QueueStatus CloseQueue(CirQueue *Queue);
size_t AddtoQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size);
size_t RemovefromQueue(CirQueue *Queue, UInt8 *Buffer, size_t MaxSize);
size_t FreeSpaceinQueue(CirQueue *Queue);
size_t UsedSpaceinQueue(CirQueue *Queue);
size_t GetQueueSize(CirQueue *Queue);
QueueStatus GetQueueStatus(CirQueue *Queue);
void CheckQueues(PortInfo_t *port);