adsp.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*****************************************************************************
  2. adsp.c
  3. This file is part of the lpstyl package.
  4. Copyright (C) 1996-2000 Monroe Williams (monroe@pobox.com)
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without
  7. modification, are permitted provided that the following conditions
  8. are met:
  9. 1. Redistributions of source code must retain the above copyright
  10. notice, this list of conditions and the following disclaimer.
  11. 2. Redistributions in binary form must reproduce the above copyright
  12. notice, this list of conditions and the following disclaimer in the
  13. documentation and/or other materials provided with the distribution.
  14. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *****************************************************************************/
  25. #include <unistd.h>
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <netatalk/at.h>
  29. #include <atalk/nbp.h>
  30. #include <string.h>
  31. #include <termios.h>
  32. #include <fcntl.h>
  33. #include <errno.h>
  34. #include "adsp.h"
  35. /* XXX -- For debugging only? */
  36. #include <stdio.h>
  37. #include <signal.h>
  38. /* local prototypes */
  39. int adsp_send_control(struct adsp_endp *endp, int flags);
  40. int adsp_send_data(struct adsp_endp *endp,
  41. int flags,
  42. char *data,
  43. int len);
  44. int adsp_send_attn(struct adsp_endp *endp,
  45. int flags,
  46. u_int16_t code,
  47. char *data,
  48. int len);
  49. int adsp_recv_packet(struct adsp_endp *endp, int block);
  50. int adsp_process_packet(char *pkt,
  51. int pktsize,
  52. struct adsp_endp *endp);
  53. int adsp_setup_endp(struct adsp_socket *s,
  54. struct adsp_endp *endp,
  55. struct sockaddr_at *addr);
  56. /* This is in libatalk (in nbp_util.c), but it doesn't look like the
  57. prototype is in any header files.
  58. */
  59. int nbp_name(char *name, char **objp, char **typep, char **zonep);
  60. int adsp_open_socket(struct adsp_socket *s)
  61. {
  62. struct sockaddr_at addr;
  63. /* In case we fail */
  64. if((s->socket = socket(AF_APPLETALK, SOCK_DGRAM, 0)) < 0)
  65. {
  66. return(s->socket);
  67. }
  68. bzero(&addr, sizeof(struct sockaddr_at));
  69. addr.sat_len = sizeof(struct sockaddr_at);
  70. addr.sat_family = AF_APPLETALK;
  71. addr.sat_addr.s_net = ATADDR_ANYNET;
  72. addr.sat_addr.s_node = ATADDR_ANYNODE;
  73. addr.sat_port = ATADDR_ANYPORT;
  74. if(bind(s->socket, (struct sockaddr*)&addr, addr.sat_len) < 0)
  75. {
  76. s->socket = -1;
  77. return(-1);
  78. }
  79. {
  80. int len = sizeof(struct sockaddr_at);
  81. if(getsockname(s->socket, (struct sockaddr*)&addr, &len) < 0)
  82. {
  83. s->socket = -1;
  84. return(-1);
  85. }
  86. }
  87. bcopy(&addr, &(s->local_addr), sizeof(struct sockaddr_at));
  88. /* XXX -- This could be done a lot better. */
  89. s->lastConnID = getpid();
  90. return(0);
  91. }
  92. int adsp_close_socket(struct adsp_socket *s)
  93. {
  94. close(s->socket);
  95. return(0);
  96. }
  97. int adsp_recv_packet(struct adsp_endp *endp, int block)
  98. {
  99. char pkt[1024];
  100. size_t len;
  101. struct sockaddr_at from;
  102. int fromlen;
  103. int result = 0;
  104. int retries = 0;
  105. int rcv_result;
  106. /* Set a the receive timeout on the socket. */
  107. {
  108. struct timeval tv;
  109. if(block == 1)
  110. {
  111. /* Normal timeout will be 30 seconds */
  112. tv.tv_sec = 30;
  113. tv.tv_usec = 0;
  114. }
  115. else if(block == 2)
  116. {
  117. /* Special case for attn retries -- 5 seconds, don't transmit
  118. keepalives.
  119. */
  120. tv.tv_sec = 5;
  121. tv.tv_usec = 0;
  122. }
  123. else
  124. {
  125. /* A timeout of 0.1 second is close enough to non-blocking
  126. for our purposes.
  127. */
  128. tv.tv_sec = 0;
  129. tv.tv_usec = 100000;
  130. }
  131. if(setsockopt(endp->local_socket->socket,
  132. SOL_SOCKET,
  133. SO_RCVTIMEO,
  134. &tv,
  135. sizeof(struct timeval)) < 0)
  136. {
  137. perror("setsockopt");
  138. }
  139. }
  140. while(1)
  141. {
  142. errno = 0;
  143. fromlen = sizeof(struct sockaddr_at);
  144. len = 1024;
  145. bcopy(&(endp->remote_addr), &from, fromlen);
  146. rcv_result = recvfrom(endp->local_socket->socket,
  147. pkt,
  148. len,
  149. 0,
  150. (struct sockaddr*)&(from),
  151. &fromlen);
  152. if(rcv_result == -1)
  153. {
  154. if(errno == EWOULDBLOCK)
  155. {
  156. /* The timer expired. */
  157. if(block == 1)
  158. {
  159. /* Blocking. Send a keepalive and retry. */
  160. switch(endp->state)
  161. {
  162. case ADSP_STATE_CLOSED:
  163. /* There are times when we don't want to retry. */
  164. return(-1);
  165. break;
  166. }
  167. if(retries < 4)
  168. {
  169. /* Send an echo request packet and try again. */
  170. adsp_send_control(endp,
  171. ADSPOP_PROBE_ACK | ADSPFLAG_ACK);
  172. retries++;
  173. continue;
  174. }
  175. else
  176. {
  177. /* That's all the retries. The connection is dead. */
  178. adsp_send_control(endp, ADSPOP_CLOSE);
  179. endp->state = ADSP_STATE_CLOSED;
  180. return(-1);
  181. }
  182. }
  183. else
  184. {
  185. /* Non-blocking, no packet pending. */
  186. return(0);
  187. }
  188. }
  189. else
  190. {
  191. /* Unknown error. Bail. */
  192. perror("recvfrom");
  193. return(-1);
  194. }
  195. }
  196. else
  197. {
  198. len = rcv_result;
  199. break;
  200. }
  201. }
  202. if(pkt[0] != DDPTYPE_ADSP)
  203. result = -1;
  204. if(result == 0)
  205. {
  206. bcopy(&from, &(endp->remote_addr), sizeof(struct sockaddr_at));
  207. result = adsp_process_packet(pkt+1, len-1, endp);
  208. }
  209. return(result);
  210. }
  211. int adsp_process_packet(char *pkt,
  212. int pktsize,
  213. struct adsp_endp *endp)
  214. {
  215. int result = 1;
  216. struct adsphdr *hdr = (struct adsphdr*)pkt;
  217. char *data = pkt + SZ_ADSPHDR;
  218. int len = pktsize - SZ_ADSPHDR;
  219. int needsAck = 0;
  220. int op = hdr->flags & ADSPOP_MASK;
  221. int32_t temp;
  222. /* convert the header from network to host byte order. */
  223. hdr->src_conn_id = ntohs(hdr->src_conn_id);
  224. hdr->first_byte_seq = ntohl(hdr->first_byte_seq);
  225. hdr->next_rcv_seq = ntohl(hdr->next_rcv_seq);
  226. hdr->rcv_window = ntohs(hdr->rcv_window);
  227. if(hdr->flags & ADSPFLAG_ACK)
  228. needsAck = 1;
  229. if(hdr->flags & ADSPFLAG_ATTN)
  230. {
  231. struct adsp_attn_data *attn = (struct adsp_attn_data *)data;
  232. attn->code = ntohs(attn->code);
  233. /* attention packet */
  234. if(endp->attn_send_seq + 1 == hdr->next_rcv_seq)
  235. {
  236. /* Update our state. */
  237. endp->attn_send_seq += 1;
  238. }
  239. if(hdr->flags & ADSPFLAG_CONTROL)
  240. {
  241. /* This is an attention ack. */
  242. }
  243. else
  244. {
  245. /* This is an attention data packet. */
  246. if((hdr->first_byte_seq == endp->attn_recv_seq) &&
  247. !endp->attn_valid)
  248. {
  249. /* This is the right sequence number, and we have room to
  250. store it.
  251. */
  252. endp->attn_valid = 1;
  253. endp->attn_code = attn->code;
  254. endp->attn_size = len - 2;
  255. bcopy(&(attn->data), endp->attn_buffer, endp->attn_size);
  256. /* For next time... */
  257. endp->attn_recv_seq++;
  258. /* Send an ack. */
  259. adsp_send_attn(endp, ADSPFLAG_CONTROL, attn->code, NULL, 0);
  260. }
  261. else if(hdr->first_byte_seq + 1 == endp->attn_recv_seq)
  262. {
  263. /* The ack got lost and they retransmitted.
  264. Send another ack.
  265. */
  266. adsp_send_attn(endp, ADSPFLAG_CONTROL, attn->code, NULL, 0);
  267. }
  268. else
  269. {
  270. /* Bad sequence number or no room for attention msg.
  271. This packet will drop.
  272. */
  273. }
  274. }
  275. }
  276. else if(hdr->flags & ADSPFLAG_CONTROL)
  277. {
  278. struct adsp_cntl_data *cntl = (struct adsp_cntl_data *)data;
  279. cntl->version = ntohs(cntl->version);
  280. cntl->dst_conn_id = ntohs(cntl->dst_conn_id);
  281. cntl->attn_rcv_seq = ntohl(cntl->attn_rcv_seq);
  282. /* control packet */
  283. endp->oldest_seq = hdr->next_rcv_seq;
  284. endp->rmt_window_seq = hdr->next_rcv_seq + hdr->rcv_window - 1;
  285. switch(op)
  286. {
  287. case ADSPOP_OPEN_REQ:
  288. case ADSPOP_OPEN_REQ_ACK:
  289. case ADSPOP_OPEN_ACK:
  290. /* Handshaking is going well. */
  291. endp->remote_connID = hdr->src_conn_id;
  292. endp->send_seq = hdr->next_rcv_seq;
  293. endp->attn_recv_seq = cntl->attn_rcv_seq;
  294. /* This changes the connection state. */
  295. if(op == ADSPOP_OPEN_REQ)
  296. endp->state = ADSP_STATE_OPEN_RCVD;
  297. else
  298. endp->state = ADSP_STATE_OPEN;
  299. if(op == ADSPOP_OPEN_REQ_ACK)
  300. {
  301. adsp_send_control(endp, ADSPOP_OPEN_ACK);
  302. needsAck = 0;
  303. }
  304. #if 0
  305. /* This is handled from inside adsp_accept(). */
  306. else if(op == ADSPOP_OPEN_REQ)
  307. {
  308. adsp_send_control(endp, ADSPOP_OPEN_REQ_ACK);
  309. needsAck = 0;
  310. }
  311. #endif
  312. break;
  313. case ADSPOP_PROBE_ACK:
  314. endp->oldest_seq = hdr->next_rcv_seq;
  315. endp->rmt_window_seq = hdr->next_rcv_seq + hdr->rcv_window - 1;
  316. break;
  317. case ADSPOP_RESET_REQ:
  318. temp = hdr->first_byte_seq - endp->recv_seq;
  319. if((temp >= 0) && (temp <= endp->recv_window))
  320. {
  321. /* This is a legal forward reset. Do it. */
  322. endp->recv_seq = hdr->first_byte_seq;
  323. endp->recv_next_input = endp->recv_next_output;
  324. endp->recv_window = ADSP_RECV_BUFFER_SIZE;
  325. }
  326. /* Ack regardless. */
  327. adsp_send_control(endp, ADSPOP_RESET_ACK);
  328. needsAck = 0;
  329. break;
  330. case ADSPOP_RESET_ACK:
  331. /* XXX -- something should happen here. */
  332. break;
  333. case ADSPOP_RETRANS:
  334. /* Slow down, we lost someone... */
  335. endp->send_seq = hdr->next_rcv_seq;
  336. endp->rmt_window_seq = hdr->next_rcv_seq + hdr->rcv_window - 1;
  337. break;
  338. /* XXX -- handle all the cases here... */
  339. default:
  340. endp->state = ADSP_STATE_CLOSED;
  341. break;
  342. }
  343. }
  344. else
  345. {
  346. /* data packet */
  347. endp->oldest_seq = hdr->next_rcv_seq;
  348. endp->rmt_window_seq = hdr->next_rcv_seq + hdr->rcv_window - 1;
  349. if(endp->recv_seq == hdr->first_byte_seq)
  350. {
  351. if(len <= endp->recv_window)
  352. {
  353. if(len > 0)
  354. {
  355. int i;
  356. /* This packet contains data.
  357. pump it into the ring buffer.
  358. */
  359. for(i=0; i < len; i++)
  360. {
  361. endp->recv_buffer[endp->recv_next_input++] = data[i];
  362. endp->recv_next_input %= ADSP_RECV_BUFFER_SIZE;
  363. }
  364. endp->recv_window -= len;
  365. endp->recv_seq += len;
  366. needsAck = 1;
  367. }
  368. if(hdr->flags & ADSPFLAG_EOM)
  369. {
  370. /* The EOM consumes a sequence number. */
  371. endp->recv_seq++;
  372. /* It also means we should push the
  373. results to the client.
  374. */
  375. result = 2;
  376. needsAck = 1;
  377. }
  378. }
  379. else
  380. {
  381. /* The input packet exceeded our window. Drop it. */
  382. }
  383. }
  384. else
  385. {
  386. /* out-of-sequence packet. Drop it on the floor. */
  387. /* adsp_send_control(endp, ADSPOP_RETRANS | ADSPFLAG_ACK); */
  388. }
  389. }
  390. if(needsAck)
  391. {
  392. /* Sender requested an ack, and one hasn't been sent yet. */
  393. adsp_send_control(endp, ADSPOP_PROBE_ACK);
  394. }
  395. return(result);
  396. }
  397. int adsp_send_data(struct adsp_endp *endp,
  398. int flags,
  399. char *data,
  400. int len)
  401. {
  402. struct
  403. {
  404. char ddptype;
  405. struct adsp_packet pkt;
  406. } __attribute__((packed)) p;
  407. p.ddptype = DDPTYPE_ADSP;
  408. p.pkt.hdr.src_conn_id = htons(endp->connID);
  409. p.pkt.hdr.first_byte_seq = htonl(endp->send_seq);
  410. p.pkt.hdr.next_rcv_seq = htonl(endp->recv_seq);
  411. p.pkt.hdr.rcv_window = htons(endp->recv_window);
  412. p.pkt.hdr.flags = flags;
  413. if(data != NULL && len != 0)
  414. bcopy(data, &(p.pkt.data), len);
  415. if(sendto(endp->local_socket->socket,
  416. &p,
  417. 1 + sizeof(struct adsphdr) + len,
  418. 0,
  419. (struct sockaddr*)&(endp->remote_addr),
  420. sizeof(struct sockaddr_at)) < 0)
  421. {
  422. return(-1);
  423. }
  424. endp->send_seq += len;
  425. if(flags & ADSPFLAG_EOM)
  426. endp->send_seq += 1;
  427. return(0);
  428. }
  429. int adsp_send_attn(struct adsp_endp *endp,
  430. int flags,
  431. u_int16_t code,
  432. char *data,
  433. int len)
  434. {
  435. struct
  436. {
  437. char ddptype;
  438. struct adsp_attn_packet pkt;
  439. } p;
  440. p.ddptype = DDPTYPE_ADSP;
  441. p.pkt.hdr.src_conn_id = htons(endp->connID);
  442. p.pkt.hdr.first_byte_seq = htonl(endp->attn_send_seq);
  443. p.pkt.hdr.next_rcv_seq = htonl(endp->attn_recv_seq);
  444. p.pkt.hdr.rcv_window = htons(0);
  445. p.pkt.hdr.flags = flags | ADSPFLAG_ATTN;
  446. p.pkt.data.code = htons(code);
  447. if(data != NULL && len > 0)
  448. bcopy(data, &(p.pkt.data.data), len);
  449. if(sendto(endp->local_socket->socket,
  450. &p,
  451. 1 + sizeof(struct adsphdr) + 2 + len,
  452. 0,
  453. (struct sockaddr*)&(endp->remote_addr),
  454. sizeof(struct sockaddr_at)) < 0)
  455. {
  456. return(-1);
  457. }
  458. return(0);
  459. }
  460. int adsp_send_control(struct adsp_endp *endp,
  461. int flags)
  462. {
  463. int sendSize;
  464. struct
  465. {
  466. char ddptype;
  467. struct adsp_cntl_packet pkt;
  468. } p;
  469. p.ddptype = DDPTYPE_ADSP;
  470. p.pkt.hdr.src_conn_id = htons(endp->connID);
  471. p.pkt.hdr.first_byte_seq = htonl(endp->send_seq);
  472. p.pkt.hdr.next_rcv_seq = htonl(endp->recv_seq);
  473. p.pkt.hdr.rcv_window = htons(endp->recv_window);
  474. p.pkt.hdr.flags = ADSPFLAG_CONTROL | flags;
  475. switch(flags & ADSPOP_MASK)
  476. {
  477. default:
  478. sendSize = SZ_ADSPHDR + 1;
  479. break;
  480. case ADSPOP_OPEN_REQ:
  481. case ADSPOP_OPEN_ACK:
  482. case ADSPOP_OPEN_REQ_ACK:
  483. case ADSPOP_OPEN_NAK:
  484. sendSize = sizeof(p);
  485. p.pkt.data.version = htons(ADSP_VERSION);
  486. p.pkt.data.dst_conn_id = htons(endp->remote_connID);
  487. p.pkt.data.attn_rcv_seq = htonl(endp->attn_recv_seq);
  488. break;
  489. }
  490. if(sendto(endp->local_socket->socket,
  491. &p,
  492. sendSize,
  493. 0,
  494. (struct sockaddr*)&(endp->remote_addr),
  495. sizeof(struct sockaddr_at)) < 0)
  496. {
  497. return(-1);
  498. }
  499. return(0);
  500. }
  501. int adsp_setup_endp(struct adsp_socket *s,
  502. struct adsp_endp *endp,
  503. struct sockaddr_at *addr)
  504. {
  505. endp->local_socket = s;
  506. if(addr != NULL)
  507. bcopy(addr, &(endp->remote_addr), sizeof(struct sockaddr_at));
  508. endp->connID = ++(s->lastConnID);
  509. endp->remote_connID = 0;
  510. endp->state = ADSP_STATE_CLOSED;
  511. endp->send_seq = 0;
  512. endp->oldest_seq = 0;
  513. endp->rmt_window_seq = 0;
  514. endp->recv_seq = 0;
  515. endp->recv_window = ADSP_RECV_BUFFER_SIZE;
  516. endp->recv_next_input = 0;
  517. endp->recv_next_output = 0;
  518. endp->attn_send_seq = 0;
  519. endp->attn_recv_seq = 0;
  520. endp->attn_valid = 0;
  521. return(0);
  522. }
  523. int adsp_connect( struct adsp_socket *s,
  524. struct adsp_endp *endp,
  525. char *name)
  526. {
  527. int count;
  528. struct nbpnve nn;
  529. char *Obj = "=";
  530. char *Type = "=";
  531. char *Zone = "*";
  532. nbp_name(name, &Obj, &Type, &Zone);
  533. count = nbp_lookup(Obj, Type, Zone, &nn, 1);
  534. if(count < 1)
  535. return(-1);
  536. /* Looking up the name worked. Set up the connection state. */
  537. adsp_setup_endp(s, endp, &(nn.nn_sat));
  538. /* Start the handshaking process. */
  539. if(adsp_send_control(endp, ADSPOP_OPEN_REQ) < 0)
  540. return(-1);
  541. endp->state = ADSP_STATE_OPEN_SENT;
  542. while(endp->state == ADSP_STATE_OPEN_SENT)
  543. {
  544. if(adsp_recv_packet(endp, 1) < 0)
  545. return(-1);
  546. }
  547. if(endp->state != ADSP_STATE_OPEN)
  548. return(-1);
  549. return(0);
  550. }
  551. int adsp_disconnect(struct adsp_endp *endp)
  552. {
  553. if(endp->state == ADSP_STATE_OPEN)
  554. adsp_send_control(endp, ADSPOP_CLOSE);
  555. endp->state = ADSP_STATE_CLOSED;
  556. return(0);
  557. }
  558. int adsp_listen(struct adsp_socket *s,
  559. struct adsp_endp *endp)
  560. {
  561. adsp_setup_endp(s, endp, NULL);
  562. endp->state = ADSP_STATE_CLOSED;
  563. /* We'll need to set up enough of the remote address to
  564. be able to receive packets.
  565. */
  566. bzero(&(endp->remote_addr), sizeof(struct sockaddr_at));
  567. endp->remote_addr.sat_len = sizeof(struct sockaddr_at);
  568. endp->remote_addr.sat_family = AF_APPLETALK;
  569. endp->remote_addr.sat_addr.s_net = ATADDR_ANYNET;
  570. endp->remote_addr.sat_addr.s_node = ATADDR_ANYNODE;
  571. endp->remote_addr.sat_port = ATADDR_ANYPORT;
  572. while(endp->state == ADSP_STATE_CLOSED)
  573. {
  574. adsp_recv_packet(endp, 1);
  575. }
  576. if(endp->state == ADSP_STATE_OPEN_RCVD)
  577. return(1);
  578. return(0);
  579. }
  580. int adsp_accept(struct adsp_endp *endp)
  581. {
  582. if(endp->state != ADSP_STATE_OPEN_RCVD)
  583. return(-1);
  584. if(adsp_send_control(endp, ADSPOP_OPEN_REQ_ACK) < 0)
  585. return(-1);
  586. endp->state = ADSP_STATE_OPEN_SENT;
  587. while(endp->state == ADSP_STATE_OPEN_SENT)
  588. {
  589. if(adsp_recv_packet(endp, 1) < 0)
  590. return(-1);
  591. }
  592. if(endp->state != ADSP_STATE_OPEN)
  593. return(-1);
  594. return(0);
  595. }
  596. int adsp_write(struct adsp_endp *endp, char *data, int len)
  597. {
  598. u_int32_t bufferStart = endp->send_seq;
  599. u_int32_t bufferEnd = bufferStart + len;
  600. int32_t bytesNow, bytesToAck;
  601. int flags;
  602. int waitResult;
  603. /* We'll stay here until the other end has ack'ed the entire buffer.
  604. Technically this is inefficient, but at least it's easy.
  605. */
  606. bytesToAck = bufferEnd - endp->oldest_seq;
  607. while(bytesToAck > 0)
  608. {
  609. flags = ADSPFLAG_ACK;
  610. /* Figure out how many bytes we want to try and transmit. */
  611. bytesNow = bufferEnd - endp->send_seq;
  612. if(bytesNow < 0)
  613. bytesNow = 0;
  614. if(bytesNow > ADSP_MAX_DATA_SIZE)
  615. bytesNow = ADSP_MAX_DATA_SIZE;
  616. if(bytesNow > (int32_t)(endp->rmt_window_seq - endp->send_seq))
  617. bytesNow = endp->rmt_window_seq - endp->send_seq;
  618. if(bytesNow > 0)
  619. {
  620. /* The last chunk of this write will be marked EOM. */
  621. if(bytesNow == bufferEnd - endp->send_seq)
  622. flags |= ADSPFLAG_EOM;
  623. if(adsp_send_data(endp, flags,
  624. data + (endp->send_seq - bufferStart),
  625. bytesNow) < 0)
  626. {
  627. return(-1);
  628. }
  629. }
  630. waitResult = adsp_recv_packet(endp, 1);
  631. if(waitResult < 0)
  632. return(-1);
  633. bytesToAck = bufferEnd - endp->oldest_seq;
  634. }
  635. return(len);
  636. }
  637. int adsp_idle(struct adsp_endp *endp)
  638. {
  639. /* Deal with all pending incoming packets. */
  640. while(adsp_recv_packet(endp, 0) > 0)
  641. ;
  642. return(0);
  643. }
  644. int adsp_read(struct adsp_endp *endp, char *data, int len)
  645. {
  646. int bytesRead = 0;
  647. int rcv_result;
  648. do
  649. {
  650. rcv_result = adsp_recv_packet(endp, 1);
  651. if(rcv_result < 0)
  652. {
  653. return(-1);
  654. }
  655. while((bytesRead < len) &&
  656. (endp->recv_next_output != endp->recv_next_input))
  657. {
  658. data[bytesRead++] = endp->recv_buffer[endp->recv_next_output++];
  659. endp->recv_next_output %= ADSP_RECV_BUFFER_SIZE;
  660. endp->recv_window++;
  661. }
  662. } while((bytesRead < len) && (rcv_result != 0));
  663. return(bytesRead);
  664. }
  665. int adsp_read_nonblock(struct adsp_endp *endp, char *data, int len)
  666. {
  667. int rcv_result;
  668. int bytesRead = 0;
  669. do
  670. {
  671. rcv_result = adsp_recv_packet(endp, 0);
  672. if(rcv_result < 0)
  673. {
  674. if(bytesRead == 0)
  675. bytesRead = -1;
  676. return(bytesRead);
  677. }
  678. while((bytesRead < len) &&
  679. (endp->recv_next_output != endp->recv_next_input))
  680. {
  681. data[bytesRead++] = endp->recv_buffer[endp->recv_next_output++];
  682. endp->recv_next_output %= ADSP_RECV_BUFFER_SIZE;
  683. endp->recv_window++;
  684. }
  685. } while((bytesRead < len) && (rcv_result > 0));
  686. return(bytesRead);
  687. }
  688. int adsp_read_attn(struct adsp_endp *endp, u_int16_t *code, char *data)
  689. {
  690. int rcv_result;
  691. rcv_result = adsp_recv_packet(endp, 2);
  692. if(rcv_result < 0)
  693. return(-1);
  694. if(endp->attn_valid)
  695. {
  696. /* An attention message has been received. */
  697. endp->attn_valid = 0;
  698. *code = endp->attn_code;
  699. bcopy(endp->attn_buffer, data, endp->attn_size);
  700. return(endp->attn_size);
  701. }
  702. return(-1);
  703. }
  704. int adsp_write_attn(struct adsp_endp *endp, u_int16_t code, char *data, int len)
  705. {
  706. int result = 0;
  707. u_int32_t initial_seq = endp->attn_send_seq;
  708. adsp_send_attn(endp, 0, code, data, len);
  709. do
  710. {
  711. result = adsp_recv_packet(endp, 1);
  712. if(result == -1)
  713. break;
  714. if(endp->attn_send_seq != initial_seq)
  715. {
  716. /* The packet has been acknowledged. We're done. */
  717. return(0);
  718. }
  719. } while(1);
  720. return(result);
  721. }
  722. int adsp_fwd_reset(struct adsp_endp *endp)
  723. {
  724. if(adsp_send_control(endp, ADSPOP_RESET_REQ) < 0)
  725. return(-1);
  726. /* XXX -- this should use timers and retries. */
  727. return(0);
  728. }