#define CLASS_NAME "OBEX" #define ATTRIBUTE_NAME "IrDA:TinyTP:LsapSel" #define NAME_LEN(x) (strlen(x) + 1) #define CLASS_NAME_LEN NAME_LEN(CLASS_NAME) #define ATTRIBUTE_NAME_LEN NAME_LEN(ATTRIBUTE_NAME) #define FILE_NAME _T("Hello.txt") #define FILE_TO_SEND _T("\\My Documents\\Hello.txt") #define MAX_PKT_SIZE 0x800 #define MAX_RECV_BUFF_LEN 0x100 #define MAX_SEND_BUFF_LEN 1030 void SendFile(void) { /* Code for sending data to an OBEX compliant device */ WSADATA wsaData; WORD wVersion = MAKEWORD(1,1); // Winsock Version 1.1 TCHAR szError[100]; if (WSAStartup(wVersion, &wsaData) != 0) { FAILURE_MESG(_T("WSAStartup")); WSACleanup(); return; } SOCKADDR_IRDA iraddr; PDEVICELIST pDL; char szServiceName[12]; char cDevice[0x100]; int cnt; BYTE IASQueryBuff[sizeof(IAS_QUERY) - 3 + IAS_MAX_ATTRIBNAME]; int IASQueryLen = sizeof(IASQueryBuff); PIAS_QUERY pIASQuery = (PIAS_QUERY) &IASQueryBuff; SOCKET ClientSock; if ((ClientSock = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET) { FAILURE_MESG(_T("socket")); WSACleanup(); return; } /* Search for the first device in range. Query that device for the OBEX LSAPSel identifier and connect using that. */ memset (cDevice, 0, sizeof (cDevice)); int nSize = sizeof (cDevice); // loop 10 times, if not found in 10 attempts then there's a problem for (cnt = 0 ; cnt < 10 ; cnt++) { if (getsockopt(ClientSock, SOL_IRLMP, IRLMP_ENUMDEVICES, cDevice, &nSize) == SOCKET_ERROR) { FAILURE_MESG(_T("getsockopt")); closesocket (ClientSock); WSACleanup(); return; } else pDL = (PDEVICELIST)cDevice; if (pDL->numDevice != 0) // Found at least one device break; Sleep(200); } if (cnt == 10) // If there isn't any device in range, exit { FAILURE_MESG(_T("Device discovery")); closesocket (ClientSock); WSACleanup(); return; } // Query IAS database // irdaClassName and irdaAttribName are case sensitive memcpy(&pIASQuery->irdaDeviceID, pDL->Device[0].irdaDeviceID, 4); memcpy(&pIASQuery->irdaClassName, CLASS_NAME, CLASS_NAME_LEN); memcpy(&pIASQuery->irdaAttribName, ATTRIBUTE_NAME, ATTRIBUTE_NAME_LEN); if (getsockopt(ClientSock, SOL_IRLMP, IRLMP_IAS_QUERY, (char *)pIASQuery, &IASQueryLen) == SOCKET_ERROR) { FAILURE_MESG(_T("getsockopt")); closesocket (ClientSock); WSACleanup(); return; } sprintf(szServiceName, "LSAP-SEL%d", pIASQuery->irdaAttribute.irdaAttribInt); memset (&iraddr, 0, sizeof(iraddr)); iraddr.irdaAddressFamily = AF_IRDA; memcpy (iraddr.irdaDeviceID, pDL->Device[0].irdaDeviceID, 4); memcpy (iraddr.irdaServiceName, szServiceName, strlen(szServiceName) + 1); for ( cnt = 0; cnt < 10 ; cnt++ ) ( connect(ClientSock, (struct sockaddr *)&iraddr, sizeof (iraddr)) == SOCKET_ERROR ) ? Sleep(200) : break; if (cnt == 10) { FAILURE_MESG(_T("connect")); closesocket (ClientSock); WSACleanup(); return; } BYTE dataBuff[MAX_SEND_BUFF_LEN]; BYTE recvBuff[MAX_RECV_BUFF_LEN]; dataBuff[0] = OBEX_CONNECT; *((unsigned short *)&dataBuff[1]) = htons((unsigned short)7); dataBuff[3] = OBEX_VERSION; dataBuff[4] = OBEX_CONNECT_FLAGS; *((unsigned short *)&dataBuff[5]) = htons((unsigned short)MAX_PKT_SIZE); if (send(ClientSock, (const char*)dataBuff, 7, 0) == SOCKET_ERROR) { FAILURE_MESG(_T("send")); closesocket (ClientSock); WSACleanup(); return; } if ((recv(ClientSock, (char *)recvBuff, MAX_RECV_BUFF_LEN, 0) == SOCKET_ERROR) || (recvBuff[0] != OBEX_SUCCESS)) { FAILURE_MESG(_T("recv")); closesocket (ClientSock); WSACleanup(); return; } wchar_t* wfn = FILE_NAME; size_t fileLen = ((wcslen(FILE_NAME)) + 1) * sizeof(wchar_t); dataBuff[0] = OBEX_PUT; *((unsigned short *)&dataBuff[1]) = htons((unsigned short)(fileLen + 6)); dataBuff[3] = OBEX_NAME; *((unsigned short *)&dataBuff[4]) = htons((unsigned short)(fileLen + 3)); /* Now convert the unicode file name text from host to network byte order */ for (int i=0; i < (int)(fileLen/2); i++) *((unsigned short *)&dataBuff[6 + 2*i]) = htons((unsigned short)wfn[i]); if (send(ClientSock, (const char*)dataBuff, fileLen + 6, 0) == SOCKET_ERROR) { FAILURE_MESG(_T("send")); closesocket(ClientSock); WSACleanup(); return; } if ((recv(ClientSock, (char *)recvBuff, MAX_RECV_BUFF_LEN, 0) == SOCKET_ERROR) || (recvBuff[0] != OBEX_CONTINUE)) { FAILURE_MESG(_T("recv")); closesocket(ClientSock); WSACleanup(); return; } // send the data in a loop, read the file FILE* fp = _wfopen(FILE_TO_SEND, _T("r")); _setmode(fp, _O_BINARY); dataBuff[0] = OBEX_PUT; dataBuff[3] = OBEX_BODY; size_t count = 0; /* Read and send 1K chunks of data to the device */ while ((count = fread(&dataBuff[6], 1, 0x400, fp)) != 0) { if (count < 0x400) { dataBuff[0] = OBEX_PUT_FINAL; dataBuff[3] = OBEX_END_OF_BODY; } *((unsigned short *)&dataBuff[1]) = htons((unsigned short)(count + 6)); *((unsigned short *)&dataBuff[4]) = htons((unsigned short)(count + 3)); if (send(ClientSock, (const char*)dataBuff, count + 6, 0) == SOCKET_ERROR) { FAILURE_MESG(_T("send")); break; } if ((recv(ClientSock, (char *)recvBuff, MAX_RECV_BUFF_LEN, 0) == SOCKET_ERROR) || ((dataBuff[0] == OBEX_PUT) && (recvBuff[0] != OBEX_CONTINUE)) || ((dataBuff[0] == OBEX_PUT_FINAL) && (recvBuff[0] != OBEX_SUCCESS))) { FAILURE_MESG(_T("recv")); break; } } fclose(fp); // An OBEX disconnect should be called here, left as this code is anyway a prototype :-) // Cleanup closesocket(ClientSock); WSACleanup(); return; }