18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "dvb_filter.h"
38c2ecf20Sopenharmony_ci#include "av7110_ipack.h"
48c2ecf20Sopenharmony_ci#include <linux/string.h>	/* for memcpy() */
58c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_civoid av7110_ipack_reset(struct ipack *p)
98c2ecf20Sopenharmony_ci{
108c2ecf20Sopenharmony_ci	p->found = 0;
118c2ecf20Sopenharmony_ci	p->cid = 0;
128c2ecf20Sopenharmony_ci	p->plength = 0;
138c2ecf20Sopenharmony_ci	p->flag1 = 0;
148c2ecf20Sopenharmony_ci	p->flag2 = 0;
158c2ecf20Sopenharmony_ci	p->hlength = 0;
168c2ecf20Sopenharmony_ci	p->mpeg = 0;
178c2ecf20Sopenharmony_ci	p->check = 0;
188c2ecf20Sopenharmony_ci	p->which = 0;
198c2ecf20Sopenharmony_ci	p->done = 0;
208c2ecf20Sopenharmony_ci	p->count = 0;
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciint av7110_ipack_init(struct ipack *p, int size,
258c2ecf20Sopenharmony_ci		      void (*func)(u8 *buf, int size, void *priv))
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	if (!(p->buf = vmalloc(size))) {
288c2ecf20Sopenharmony_ci		printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
298c2ecf20Sopenharmony_ci		return -ENOMEM;
308c2ecf20Sopenharmony_ci	}
318c2ecf20Sopenharmony_ci	p->size = size;
328c2ecf20Sopenharmony_ci	p->func = func;
338c2ecf20Sopenharmony_ci	p->repack_subids = 0;
348c2ecf20Sopenharmony_ci	av7110_ipack_reset(p);
358c2ecf20Sopenharmony_ci	return 0;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_civoid av7110_ipack_free(struct ipack *p)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	vfree(p->buf);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic void send_ipack(struct ipack *p)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	int off;
488c2ecf20Sopenharmony_ci	struct dvb_audio_info ai;
498c2ecf20Sopenharmony_ci	int ac3_off = 0;
508c2ecf20Sopenharmony_ci	int streamid = 0;
518c2ecf20Sopenharmony_ci	int nframes = 0;
528c2ecf20Sopenharmony_ci	int f = 0;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	switch (p->mpeg) {
558c2ecf20Sopenharmony_ci	case 2:
568c2ecf20Sopenharmony_ci		if (p->count < 10)
578c2ecf20Sopenharmony_ci			return;
588c2ecf20Sopenharmony_ci		p->buf[3] = p->cid;
598c2ecf20Sopenharmony_ci		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
608c2ecf20Sopenharmony_ci		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
618c2ecf20Sopenharmony_ci		if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
628c2ecf20Sopenharmony_ci			off = 9 + p->buf[8];
638c2ecf20Sopenharmony_ci			streamid = p->buf[off];
648c2ecf20Sopenharmony_ci			if ((streamid & 0xf8) == 0x80) {
658c2ecf20Sopenharmony_ci				ai.off = 0;
668c2ecf20Sopenharmony_ci				ac3_off = ((p->buf[off + 2] << 8)|
678c2ecf20Sopenharmony_ci					   p->buf[off + 3]);
688c2ecf20Sopenharmony_ci				if (ac3_off < p->count)
698c2ecf20Sopenharmony_ci					f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
708c2ecf20Sopenharmony_ci								   p->count - ac3_off, &ai, 0);
718c2ecf20Sopenharmony_ci				if (!f) {
728c2ecf20Sopenharmony_ci					nframes = (p->count - off - 3 - ac3_off) /
738c2ecf20Sopenharmony_ci						ai.framesize + 1;
748c2ecf20Sopenharmony_ci					p->buf[off + 2] = (ac3_off >> 8) & 0xff;
758c2ecf20Sopenharmony_ci					p->buf[off + 3] = (ac3_off) & 0xff;
768c2ecf20Sopenharmony_ci					p->buf[off + 1] = nframes;
778c2ecf20Sopenharmony_ci					ac3_off +=  nframes * ai.framesize - p->count;
788c2ecf20Sopenharmony_ci				}
798c2ecf20Sopenharmony_ci			}
808c2ecf20Sopenharmony_ci		}
818c2ecf20Sopenharmony_ci		p->func(p->buf, p->count, p->data);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		p->buf[6] = 0x80;
848c2ecf20Sopenharmony_ci		p->buf[7] = 0x00;
858c2ecf20Sopenharmony_ci		p->buf[8] = 0x00;
868c2ecf20Sopenharmony_ci		p->count = 9;
878c2ecf20Sopenharmony_ci		if (p->repack_subids && p->cid == PRIVATE_STREAM1
888c2ecf20Sopenharmony_ci		    && (streamid & 0xf8) == 0x80) {
898c2ecf20Sopenharmony_ci			p->count += 4;
908c2ecf20Sopenharmony_ci			p->buf[9] = streamid;
918c2ecf20Sopenharmony_ci			p->buf[10] = (ac3_off >> 8) & 0xff;
928c2ecf20Sopenharmony_ci			p->buf[11] = (ac3_off) & 0xff;
938c2ecf20Sopenharmony_ci			p->buf[12] = 0;
948c2ecf20Sopenharmony_ci		}
958c2ecf20Sopenharmony_ci		break;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	case 1:
988c2ecf20Sopenharmony_ci		if (p->count < 8)
998c2ecf20Sopenharmony_ci			return;
1008c2ecf20Sopenharmony_ci		p->buf[3] = p->cid;
1018c2ecf20Sopenharmony_ci		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
1028c2ecf20Sopenharmony_ci		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
1038c2ecf20Sopenharmony_ci		p->func(p->buf, p->count, p->data);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci		p->buf[6] = 0x0f;
1068c2ecf20Sopenharmony_ci		p->count = 7;
1078c2ecf20Sopenharmony_ci		break;
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_civoid av7110_ipack_flush(struct ipack *p)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
1158c2ecf20Sopenharmony_ci		return;
1168c2ecf20Sopenharmony_ci	p->plength = p->found - 6;
1178c2ecf20Sopenharmony_ci	p->found = 0;
1188c2ecf20Sopenharmony_ci	send_ipack(p);
1198c2ecf20Sopenharmony_ci	av7110_ipack_reset(p);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic void write_ipack(struct ipack *p, const u8 *data, int count)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	u8 headr[3] = { 0x00, 0x00, 0x01 };
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (p->count < 6) {
1288c2ecf20Sopenharmony_ci		memcpy(p->buf, headr, 3);
1298c2ecf20Sopenharmony_ci		p->count = 6;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	if (p->count + count < p->size){
1338c2ecf20Sopenharmony_ci		memcpy(p->buf+p->count, data, count);
1348c2ecf20Sopenharmony_ci		p->count += count;
1358c2ecf20Sopenharmony_ci	} else {
1368c2ecf20Sopenharmony_ci		int rest = p->size - p->count;
1378c2ecf20Sopenharmony_ci		memcpy(p->buf+p->count, data, rest);
1388c2ecf20Sopenharmony_ci		p->count += rest;
1398c2ecf20Sopenharmony_ci		send_ipack(p);
1408c2ecf20Sopenharmony_ci		if (count - rest > 0)
1418c2ecf20Sopenharmony_ci			write_ipack(p, data + rest, count - rest);
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciint av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	int l;
1498c2ecf20Sopenharmony_ci	int c = 0;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	while (c < count && (p->mpeg == 0 ||
1528c2ecf20Sopenharmony_ci			     (p->mpeg == 1 && p->found < 7) ||
1538c2ecf20Sopenharmony_ci			     (p->mpeg == 2 && p->found < 9))
1548c2ecf20Sopenharmony_ci	       &&  (p->found < 5 || !p->done)) {
1558c2ecf20Sopenharmony_ci		switch (p->found) {
1568c2ecf20Sopenharmony_ci		case 0:
1578c2ecf20Sopenharmony_ci		case 1:
1588c2ecf20Sopenharmony_ci			if (buf[c] == 0x00)
1598c2ecf20Sopenharmony_ci				p->found++;
1608c2ecf20Sopenharmony_ci			else
1618c2ecf20Sopenharmony_ci				p->found = 0;
1628c2ecf20Sopenharmony_ci			c++;
1638c2ecf20Sopenharmony_ci			break;
1648c2ecf20Sopenharmony_ci		case 2:
1658c2ecf20Sopenharmony_ci			if (buf[c] == 0x01)
1668c2ecf20Sopenharmony_ci				p->found++;
1678c2ecf20Sopenharmony_ci			else if (buf[c] == 0)
1688c2ecf20Sopenharmony_ci				p->found = 2;
1698c2ecf20Sopenharmony_ci			else
1708c2ecf20Sopenharmony_ci				p->found = 0;
1718c2ecf20Sopenharmony_ci			c++;
1728c2ecf20Sopenharmony_ci			break;
1738c2ecf20Sopenharmony_ci		case 3:
1748c2ecf20Sopenharmony_ci			p->cid = 0;
1758c2ecf20Sopenharmony_ci			switch (buf[c]) {
1768c2ecf20Sopenharmony_ci			case PROG_STREAM_MAP:
1778c2ecf20Sopenharmony_ci			case PRIVATE_STREAM2:
1788c2ecf20Sopenharmony_ci			case PROG_STREAM_DIR:
1798c2ecf20Sopenharmony_ci			case ECM_STREAM     :
1808c2ecf20Sopenharmony_ci			case EMM_STREAM     :
1818c2ecf20Sopenharmony_ci			case PADDING_STREAM :
1828c2ecf20Sopenharmony_ci			case DSM_CC_STREAM  :
1838c2ecf20Sopenharmony_ci			case ISO13522_STREAM:
1848c2ecf20Sopenharmony_ci				p->done = 1;
1858c2ecf20Sopenharmony_ci				fallthrough;
1868c2ecf20Sopenharmony_ci			case PRIVATE_STREAM1:
1878c2ecf20Sopenharmony_ci			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1888c2ecf20Sopenharmony_ci			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1898c2ecf20Sopenharmony_ci				p->found++;
1908c2ecf20Sopenharmony_ci				p->cid = buf[c];
1918c2ecf20Sopenharmony_ci				c++;
1928c2ecf20Sopenharmony_ci				break;
1938c2ecf20Sopenharmony_ci			default:
1948c2ecf20Sopenharmony_ci				p->found = 0;
1958c2ecf20Sopenharmony_ci				break;
1968c2ecf20Sopenharmony_ci			}
1978c2ecf20Sopenharmony_ci			break;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci		case 4:
2008c2ecf20Sopenharmony_ci			if (count-c > 1) {
2018c2ecf20Sopenharmony_ci				p->plen[0] = buf[c];
2028c2ecf20Sopenharmony_ci				c++;
2038c2ecf20Sopenharmony_ci				p->plen[1] = buf[c];
2048c2ecf20Sopenharmony_ci				c++;
2058c2ecf20Sopenharmony_ci				p->found += 2;
2068c2ecf20Sopenharmony_ci				p->plength = (p->plen[0] << 8) | p->plen[1];
2078c2ecf20Sopenharmony_ci			} else {
2088c2ecf20Sopenharmony_ci				p->plen[0] = buf[c];
2098c2ecf20Sopenharmony_ci				p->found++;
2108c2ecf20Sopenharmony_ci				return count;
2118c2ecf20Sopenharmony_ci			}
2128c2ecf20Sopenharmony_ci			break;
2138c2ecf20Sopenharmony_ci		case 5:
2148c2ecf20Sopenharmony_ci			p->plen[1] = buf[c];
2158c2ecf20Sopenharmony_ci			c++;
2168c2ecf20Sopenharmony_ci			p->found++;
2178c2ecf20Sopenharmony_ci			p->plength = (p->plen[0] << 8) | p->plen[1];
2188c2ecf20Sopenharmony_ci			break;
2198c2ecf20Sopenharmony_ci		case 6:
2208c2ecf20Sopenharmony_ci			if (!p->done) {
2218c2ecf20Sopenharmony_ci				p->flag1 = buf[c];
2228c2ecf20Sopenharmony_ci				c++;
2238c2ecf20Sopenharmony_ci				p->found++;
2248c2ecf20Sopenharmony_ci				if ((p->flag1 & 0xc0) == 0x80)
2258c2ecf20Sopenharmony_ci					p->mpeg = 2;
2268c2ecf20Sopenharmony_ci				else {
2278c2ecf20Sopenharmony_ci					p->hlength = 0;
2288c2ecf20Sopenharmony_ci					p->which = 0;
2298c2ecf20Sopenharmony_ci					p->mpeg = 1;
2308c2ecf20Sopenharmony_ci					p->flag2 = 0;
2318c2ecf20Sopenharmony_ci				}
2328c2ecf20Sopenharmony_ci			}
2338c2ecf20Sopenharmony_ci			break;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci		case 7:
2368c2ecf20Sopenharmony_ci			if (!p->done && p->mpeg == 2) {
2378c2ecf20Sopenharmony_ci				p->flag2 = buf[c];
2388c2ecf20Sopenharmony_ci				c++;
2398c2ecf20Sopenharmony_ci				p->found++;
2408c2ecf20Sopenharmony_ci			}
2418c2ecf20Sopenharmony_ci			break;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		case 8:
2448c2ecf20Sopenharmony_ci			if (!p->done && p->mpeg == 2) {
2458c2ecf20Sopenharmony_ci				p->hlength = buf[c];
2468c2ecf20Sopenharmony_ci				c++;
2478c2ecf20Sopenharmony_ci				p->found++;
2488c2ecf20Sopenharmony_ci			}
2498c2ecf20Sopenharmony_ci			break;
2508c2ecf20Sopenharmony_ci		}
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	if (c == count)
2548c2ecf20Sopenharmony_ci		return count;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (!p->plength)
2578c2ecf20Sopenharmony_ci		p->plength = MMAX_PLENGTH - 6;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
2608c2ecf20Sopenharmony_ci			(p->mpeg == 1 && p->found >= 7))) {
2618c2ecf20Sopenharmony_ci		switch (p->cid) {
2628c2ecf20Sopenharmony_ci		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
2638c2ecf20Sopenharmony_ci		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
2648c2ecf20Sopenharmony_ci		case PRIVATE_STREAM1:
2658c2ecf20Sopenharmony_ci			if (p->mpeg == 2 && p->found == 9) {
2668c2ecf20Sopenharmony_ci				write_ipack(p, &p->flag1, 1);
2678c2ecf20Sopenharmony_ci				write_ipack(p, &p->flag2, 1);
2688c2ecf20Sopenharmony_ci				write_ipack(p, &p->hlength, 1);
2698c2ecf20Sopenharmony_ci			}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci			if (p->mpeg == 1 && p->found == 7)
2728c2ecf20Sopenharmony_ci				write_ipack(p, &p->flag1, 1);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci			if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
2758c2ecf20Sopenharmony_ci			    p->found < 14) {
2768c2ecf20Sopenharmony_ci				while (c < count && p->found < 14) {
2778c2ecf20Sopenharmony_ci					p->pts[p->found - 9] = buf[c];
2788c2ecf20Sopenharmony_ci					write_ipack(p, buf + c, 1);
2798c2ecf20Sopenharmony_ci					c++;
2808c2ecf20Sopenharmony_ci					p->found++;
2818c2ecf20Sopenharmony_ci				}
2828c2ecf20Sopenharmony_ci				if (c == count)
2838c2ecf20Sopenharmony_ci					return count;
2848c2ecf20Sopenharmony_ci			}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci			if (p->mpeg == 1 && p->which < 2000) {
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci				if (p->found == 7) {
2898c2ecf20Sopenharmony_ci					p->check = p->flag1;
2908c2ecf20Sopenharmony_ci					p->hlength = 1;
2918c2ecf20Sopenharmony_ci				}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci				while (!p->which && c < count &&
2948c2ecf20Sopenharmony_ci				       p->check == 0xff){
2958c2ecf20Sopenharmony_ci					p->check = buf[c];
2968c2ecf20Sopenharmony_ci					write_ipack(p, buf + c, 1);
2978c2ecf20Sopenharmony_ci					c++;
2988c2ecf20Sopenharmony_ci					p->found++;
2998c2ecf20Sopenharmony_ci					p->hlength++;
3008c2ecf20Sopenharmony_ci				}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci				if (c == count)
3038c2ecf20Sopenharmony_ci					return count;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci				if ((p->check & 0xc0) == 0x40 && !p->which) {
3068c2ecf20Sopenharmony_ci					p->check = buf[c];
3078c2ecf20Sopenharmony_ci					write_ipack(p, buf + c, 1);
3088c2ecf20Sopenharmony_ci					c++;
3098c2ecf20Sopenharmony_ci					p->found++;
3108c2ecf20Sopenharmony_ci					p->hlength++;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci					p->which = 1;
3138c2ecf20Sopenharmony_ci					if (c == count)
3148c2ecf20Sopenharmony_ci						return count;
3158c2ecf20Sopenharmony_ci					p->check = buf[c];
3168c2ecf20Sopenharmony_ci					write_ipack(p, buf + c, 1);
3178c2ecf20Sopenharmony_ci					c++;
3188c2ecf20Sopenharmony_ci					p->found++;
3198c2ecf20Sopenharmony_ci					p->hlength++;
3208c2ecf20Sopenharmony_ci					p->which = 2;
3218c2ecf20Sopenharmony_ci					if (c == count)
3228c2ecf20Sopenharmony_ci						return count;
3238c2ecf20Sopenharmony_ci				}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci				if (p->which == 1) {
3268c2ecf20Sopenharmony_ci					p->check = buf[c];
3278c2ecf20Sopenharmony_ci					write_ipack(p, buf + c, 1);
3288c2ecf20Sopenharmony_ci					c++;
3298c2ecf20Sopenharmony_ci					p->found++;
3308c2ecf20Sopenharmony_ci					p->hlength++;
3318c2ecf20Sopenharmony_ci					p->which = 2;
3328c2ecf20Sopenharmony_ci					if (c == count)
3338c2ecf20Sopenharmony_ci						return count;
3348c2ecf20Sopenharmony_ci				}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci				if ((p->check & 0x30) && p->check != 0xff) {
3378c2ecf20Sopenharmony_ci					p->flag2 = (p->check & 0xf0) << 2;
3388c2ecf20Sopenharmony_ci					p->pts[0] = p->check;
3398c2ecf20Sopenharmony_ci					p->which = 3;
3408c2ecf20Sopenharmony_ci				}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci				if (c == count)
3438c2ecf20Sopenharmony_ci					return count;
3448c2ecf20Sopenharmony_ci				if (p->which > 2){
3458c2ecf20Sopenharmony_ci					if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
3468c2ecf20Sopenharmony_ci						while (c < count && p->which < 7) {
3478c2ecf20Sopenharmony_ci							p->pts[p->which - 2] = buf[c];
3488c2ecf20Sopenharmony_ci							write_ipack(p, buf + c, 1);
3498c2ecf20Sopenharmony_ci							c++;
3508c2ecf20Sopenharmony_ci							p->found++;
3518c2ecf20Sopenharmony_ci							p->which++;
3528c2ecf20Sopenharmony_ci							p->hlength++;
3538c2ecf20Sopenharmony_ci						}
3548c2ecf20Sopenharmony_ci						if (c == count)
3558c2ecf20Sopenharmony_ci							return count;
3568c2ecf20Sopenharmony_ci					} else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
3578c2ecf20Sopenharmony_ci						while (c < count && p->which < 12) {
3588c2ecf20Sopenharmony_ci							if (p->which < 7)
3598c2ecf20Sopenharmony_ci								p->pts[p->which - 2] = buf[c];
3608c2ecf20Sopenharmony_ci							write_ipack(p, buf + c, 1);
3618c2ecf20Sopenharmony_ci							c++;
3628c2ecf20Sopenharmony_ci							p->found++;
3638c2ecf20Sopenharmony_ci							p->which++;
3648c2ecf20Sopenharmony_ci							p->hlength++;
3658c2ecf20Sopenharmony_ci						}
3668c2ecf20Sopenharmony_ci						if (c == count)
3678c2ecf20Sopenharmony_ci							return count;
3688c2ecf20Sopenharmony_ci					}
3698c2ecf20Sopenharmony_ci					p->which = 2000;
3708c2ecf20Sopenharmony_ci				}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci			}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci			while (c < count && p->found < p->plength + 6) {
3758c2ecf20Sopenharmony_ci				l = count - c;
3768c2ecf20Sopenharmony_ci				if (l + p->found > p->plength + 6)
3778c2ecf20Sopenharmony_ci					l = p->plength + 6 - p->found;
3788c2ecf20Sopenharmony_ci				write_ipack(p, buf + c, l);
3798c2ecf20Sopenharmony_ci				p->found += l;
3808c2ecf20Sopenharmony_ci				c += l;
3818c2ecf20Sopenharmony_ci			}
3828c2ecf20Sopenharmony_ci			break;
3838c2ecf20Sopenharmony_ci		}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		if (p->done) {
3878c2ecf20Sopenharmony_ci			if (p->found + count - c < p->plength + 6) {
3888c2ecf20Sopenharmony_ci				p->found += count - c;
3898c2ecf20Sopenharmony_ci				c = count;
3908c2ecf20Sopenharmony_ci			} else {
3918c2ecf20Sopenharmony_ci				c += p->plength + 6 - p->found;
3928c2ecf20Sopenharmony_ci				p->found = p->plength + 6;
3938c2ecf20Sopenharmony_ci			}
3948c2ecf20Sopenharmony_ci		}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		if (p->plength && p->found == p->plength + 6) {
3978c2ecf20Sopenharmony_ci			send_ipack(p);
3988c2ecf20Sopenharmony_ci			av7110_ipack_reset(p);
3998c2ecf20Sopenharmony_ci			if (c < count)
4008c2ecf20Sopenharmony_ci				av7110_ipack_instant_repack(buf + c, count - c, p);
4018c2ecf20Sopenharmony_ci		}
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci	return count;
4048c2ecf20Sopenharmony_ci}
405