1/*
2    File:       IrDscInfo.cpp
3
4    Contains:   Implementation of IrDscInfo (XID discovery/device info) class
5
6
7*/
8
9#include "IrDscInfo.h"
10#include "CBufferSegment.h"
11//#include "IrConstData.h"
12
13#define super OSObject
14    OSDefineMetaClassAndStructors(TIrDscInfo, OSObject);
15
16//--------------------------------------------------------------------------------
17//      TIrDscInfo
18//--------------------------------------------------------------------------------
19TIrDscInfo *
20TIrDscInfo::tIrDscInfo()
21{
22    TIrDscInfo *obj = new TIrDscInfo;
23    if (obj && !obj->init()) {
24	obj->release();
25	obj = nil;
26    }
27    return obj;
28}
29
30void
31TIrDscInfo::free()
32{
33    super::free();
34}
35
36
37bool
38TIrDscInfo::init()
39{
40
41    fDevAddr = 0;
42    fHints = 0;
43    fVersion = 0;
44    fCharset = 0;
45    bzero(fNickname, sizeof(fNickname));
46    bzero(fHintCount, sizeof(fHintCount));
47
48    if (!super::init()) return false;
49
50    return true;
51} // TIrDscInfo::init
52
53
54//--------------------------------------------------------------------------------
55//      SetServiceHints
56//--------------------------------------------------------------------------------
57void TIrDscInfo::SetServiceHints( ULong hints )
58{
59    fHints |= hints;
60
61    for( int index = 0; index < kHintCount; index++ ) {
62	if( hints & ( 1<<index ) )
63	    fHintCount[index]++;
64    }
65}
66
67
68//--------------------------------------------------------------------------------
69//      RemoveServiceHints
70//--------------------------------------------------------------------------------
71void TIrDscInfo::RemoveServiceHints( ULong hints )
72{
73    for( int index = 0; index < kHintCount; index++ ) {
74	ULong   hintMask = 1<<index;
75	if( hints & hintMask ) {
76	    fHintCount[index]--;
77	    if( fHintCount[index] == 0 )
78		fHints &= ~hintMask;
79	}
80    }
81}
82
83
84//--------------------------------------------------------------------------------
85//      SetNickname
86//--------------------------------------------------------------------------------
87IrDAErr TIrDscInfo::SetNickname(const char* name)
88{
89    ULong nameLen;
90
91    nameLen = strlen(name);
92    if (nameLen > kMaxNicknameLen) {
93	return errBadArg;
94    }
95
96    strlcpy((char*)&fNickname[0], name, sizeof(fNickname));
97    return noErr;
98
99} // TIrDscInfo::SetNickname
100
101
102//--------------------------------------------------------------------------------
103//      GetNickname
104//--------------------------------------------------------------------------------
105void TIrDscInfo::GetNickname(UChar* name, int maxnamelen)
106{
107    // Note: name provided must be at least kMaxNicknameLen chars long
108    // It is responsibility of IrGlue code that uses this to ensure that.
109    strlcpy((char*)name, (const char*)&fNickname[0], maxnamelen);
110
111} // TIrDscInfo::GetNickname
112
113
114//--------------------------------------------------------------------------------
115//      AddDevInfoToBuffer
116//--------------------------------------------------------------------------------
117ULong TIrDscInfo::AddDevInfoToBuffer(UByte* buffer, ULong maxBytes)
118{
119#pragma unused(maxBytes)
120
121    UByte hintByte;
122    ULong index;
123    ULong hints;
124    ULong nameLen;
125    ULong devInfoLen = 0;
126
127    // Store the hint byte(s)
128    for (hints = fHints, index = 0; index < 4; index++) {
129	// Mask off next hint byte
130	hintByte = (UByte)(hints & 0xFF);
131	hints >>= 8;
132
133	// If more hint bytes, set the extension bit
134	if (hints != 0) {
135	    hintByte |= kDevInfoHintExtension1;
136	}
137	else        // jdg: protect us from garbage hints being set
138	    hintByte &= ~kDevInfoHintExtension1;    // make sure it's off
139
140	// Store the hintByte, inc byte count
141	*buffer++ = hintByte;
142	devInfoLen++;
143
144	// No more hint bytes?
145	if (hints == 0) break;
146    }
147
148    // Add the character set encoding (I'm only supporting ASCII for now)
149    *buffer++ = GetCharacterSet();
150    devInfoLen++;
151
152    // Figure out how much of the name can be written out
153    nameLen = Min(strlen((const char*)&fNickname[0]), kMaxNicknameLen - (devInfoLen - 2));
154    memcpy(buffer, fNickname, (unsigned int)nameLen);
155    devInfoLen += nameLen;
156
157    return devInfoLen;
158
159} // TIrDscInfo::AddDevInfoToBuffer
160
161
162//--------------------------------------------------------------------------------
163//      ExtractDevInfoFromBuffer
164//--------------------------------------------------------------------------------
165IrDAErr TIrDscInfo::ExtractDevInfoFromBuffer(CBufferSegment *buffer)
166{
167    UByte hintByte;
168    ULong index;
169    ULong bytesRead;
170    UByte devInfo[4 + 1 + kMaxNicknameLen];
171
172    // Initialize fields (in case no devInfo was provided - which is supposedly okay?)
173    fHints = 0;
174    fNickname[0] = 0;
175
176    // Read in maximum
177    bytesRead = buffer->Getn(&devInfo[0], sizeof(devInfo));
178
179    // Parse the hint byte(s)
180    for (index = 0; index < bytesRead; ) {
181	hintByte = devInfo[index];
182	fHints |= (hintByte & ~kDevInfoHintExtension1) << (index * 8);
183	index++;
184	if ((hintByte & kDevInfoHintExtension1) == 0) break;
185    }
186
187    // Parse the char set byte
188    if (index < bytesRead) {
189	SetCharacterSet(devInfo[index++]);
190    }
191
192    // Now extract the device name (and null terminate it)
193    memcpy(fNickname, &devInfo[index], (unsigned int)(bytesRead - index));
194    fNickname[bytesRead - index] = 0;
195
196    return noErr;
197
198} // TIrDscInfo::ExtractDevInfoFromBuffer
199
200